35

クライアントからサーバーにオブジェクトを渡します。string.emptyとして表されるオブジェクトのプロパティは、このプロセス中にnullに変換されます。オブジェクト型がstring.emptyをサポートしている場合、これを防ぐ方法を考えていました。

ここに画像の説明を入力してください

console.log("DataToPost:", dataToPost);

$.ajax({
    type: "POST",
    contentType: 'application/json'
    url: "../../csweb/Orders/SaveOrderDetails/",
    data: dataToPost,
    success: function (result) {
        console.log(result);
    },
    error: function (e) {
        console.error(e);
    }
});

ここに画像の説明を入力してください

私のモデルにはnull許容のDateTimeオブジェクトが含まれています。サーバー上ですべてのnullをstring.emptyに強制することはできません。

AutoMapperを使用しているので、サーバー上でプロパティを個別に検査する必要はありません。

4

5 に答える 5

75

これは、空の文字列をnullsにバインドするMVC機能です。

このロジックは、によって使用されるModelMetadata.ConvertEmptyStringToNullプロパティで制御されますDefaultModelBinder

属性ConvertEmptyStringToNullで設定できますDisplayFormat

public class OrderDetailsModel
{
    [DisplayFormat(ConvertEmptyStringToNull = false)]
    public string Comment { get; set; }

    //...
}

ただし、すべてのプロパティに注釈を付けたくない場合は、falseに設定したカスタムモデルバインダーを作成できます。

public class EmptyStringModelBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext,
                                     ModelBindingContext bindingContext)
    {
        bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
        Binders = new ModelBinderDictionary() { DefaultBinder = this };
        return base.BindModel(controllerContext, bindingContext);
    }
}

また、アクションでModelBinderAttributeを使用できます。

public ActionResult SaveOrderDetails([ModelBinder(typeof(EmptyStringModelBinder))] 
       OrderDetailsModel orderDetailsModel)
{
}

または、Global.asaxでグローバルにデフォルトModelBinderとして設定できます。

ModelBinders.Binders.DefaultBinder = new EmptyStringModelBinder();

この機能の詳細については、こちらをご覧ください。

于 2012-10-04T19:21:32.117 に答える
10

いくつかの回答が示唆するようにModelMetadataを変更するModelBinderを作成する代わりに、よりクリーンな代替手段はカスタムModelMetadataProviderを提供することです。

public class EmptyStringDataAnnotationsModelMetadataProvider : System.Web.Mvc.DataAnnotationsModelMetadataProvider 
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var modelMetadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        modelMetadata.ConvertEmptyStringToNull = false;
        return modelMetadata;
    }
}

次に、Application_Start()で

ModelMetadataProviders.Current = new EmptyStringDataAnnotationsModelMetadataProvider();
于 2013-12-01T14:39:48.713 に答える
3

受け入れられた答えは、MVC4を使用して私には機能しませんでした。ただし、次の回避策は有効であり、他の人に役立つと思いました。

public class CustomModelBinder : DefaultModelBinder
{
    public bool ConvertEmptyStringToNull { get; set; }

    public CustomModelBinder ()
    {
    }

    public CustomModelBinder (bool convertEmptyStringToNull)
    {
        this.ConvertEmptyStringToNull = convertEmptyStringToNull;
    }

    protected override bool OnModelUpdating(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // this little bit is required to override the ConvertEmptyStringToNull functionality that we do not want!

        foreach (string propertyKey in bindingContext.PropertyMetadata.Keys)
        {
            if(bindingContext.PropertyMetadata[propertyKey] != null)
                    bindingContext.PropertyMetadata[propertyKey].ConvertEmptyStringToNull = this.ConvertEmptyStringToNull;
        }
        return base.OnModelUpdating(controllerContext, bindingContext);
    }


}

これにより、MVC4+での問題が修正されます。bindingContext.ModelMetadata.ConvertEmptyStringToNullは完全に無視されているように見えます。これは、バインドされている各プロパティのPropertyMetadataオブジェクトに設定が存在するためです。PropertyMetadataはBindProperty()で再作成されるため、そのメソッド呼び出しの前に設定すると、バインドされているオブジェクトのプロパティの属性として存在しない限り([DisplayFormat(ConvertEmptyStringToNull = false)]など)上書きされます。それはばかげているので、誰もすべてのプロパティでこれをしたくありません。

于 2013-10-10T18:29:52.303 に答える
0

を使用してデータを投稿する場合$.ajax、はオプションnullのプロパティの可能な値ではありません。datahttpデバッガーでリクエストを見ると、空の文字列に変換されていることがわかります。

したがって、MVCコントローラーは反対の変換を適用していると思います。

この問題を解決するためにajaxアプリケーションで行うことは、のdataオプションを使用しないことです$.ajax()が、すべてをJSONでシリアル化し、データオプションの単一のフィールド「データ」に入れます。そのように、null値に問題はありません。もちろん、サーバー側で逆シリアル化する必要があります。

于 2012-10-04T19:21:27.660 に答える
0

問題は、文字列が空の場合、AutoMapperがnullableをnullに変換することです。この他の質問は、あなたのニーズに十分であると私が信じる何かで答えられました:空にするAutomappernull文字列

于 2012-10-04T19:16:45.677 に答える