0

カスタムモデルバインダーで問題に直面しています。

EditorTemplates によって表示される 2 つのモデル (基本クラスから継承) があります。

ベースクラス:

public abstract class QuestionAnswerInputModel {
    public Guid QuestionId {
        get; set;
    }
}

モデルクラス 1:

public class RatingQuestionInputModel : QuestionAnswerInputModel{
    [Required]
    [Range(1,4)]
    public int? Rating { get; set; }
}

モデルクラス 2:

public class FreeTextQuestionInputModel: QuestionAnswerInputModel{
    [Required]
    public string FreeText { get; set; }
}

それをバインドするために、カスタム モデルバインダーを実装しました。

public class QuestionAnswerModelBinder : DefaultModelBinder {
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {

        QuestionAnswerInputModel model;

        if ((typeof(QuestionAnswerInputModel) != bindingContext.ModelType)) {
            return null;
        }

        ModelBindingContext context = new ModelBindingContext(bindingContext);

        Type typeOfModel;

        string prefix = bindingContext.ModelName;
        if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new FreeTextQuestionInputModel().GetPropertyName(m => m.FreeText))) {
            typeOfModel = typeof(FreeTextQuestionInputModel);
        } else if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new RatingQuestionInputModel().GetPropertyName(m => m.Rating))) {
            typeOfModel = typeof(RatingQuestionInputModel);
        } else {
            return null;
        }

        context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(), bindingContext.ModelMetadata.ContainerType, null, typeOfModel, bindingContext.ModelName);
        return base.BindModel(controllerContext, context);
    }
}

全体としてうまく機能しますが、モデル (QuestionId および Rating/Freetext) のプロパティの値が設定されていませんか? 誰でも理由を教えてもらえますか? 私は何を間違っていますか?

私も電話してみた

new DefaultModelBinder().BindModel(controllerContext, context)

しかし、結果は同じです。オブジェクトは正しくインスタンス化されていますが、プロパティが設定されていません。


アップデート:

この投稿MVC 3 Model Binding a Sub Type (Abstract Class or Interface)のように、DefaultBinder の CreateModel-Methode だけをオーバーライドしようとしました。

protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) {

        if ((typeof(QuestionAnswerInputModel) != bindingContext.ModelType)) {
            return null;
        }

        string prefix = bindingContext.ModelName;
        if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new FreeTextQuestionInputModel().GetPropertyName(m => m.FreeText))) {
            return new FreeTextQuestionInputModel();
        } else if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new RatingQuestionInputModel().GetPropertyName(m => m.Rating))) {
            return new RatingQuestionInputModel();
        } else {
            return null;
        }
    }

モデルはまだ正しくインスタンス化されています。問題は、基本クラスのプロパティのみが設定されていることです。

4

1 に答える 1

0

@macpak との話し合いの後、解決策を見つけました。これは私にとってうまくいきます:

protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) {

    if ((typeof(QuestionAnswerInputModel) != bindingContext.ModelType)) {
        return null;
    }

    string prefix = bindingContext.ModelName;

    QuestionAnswerInputModel obj;
    if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new FreeTextQuestionInputModel().GetPropertyName(m => m.FreeText))) {
        obj = new FreeTextQuestionInputModel();
    } else if (bindingContext.ValueProvider.ContainsPrefix(prefix + "." + new RatingQuestionInputModel().GetPropertyName(m => m.Rating))) {
        obj = new RatingQuestionInputModel();
    } else {
        return null;
    }

    bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, obj.GetType());
    bindingContext.ModelMetadata.Model = obj;

    return obj;
}

CreateModel-Methode をオーバーライドするだけです。@MacPakに感謝します!

于 2014-11-27T15:47:39.947 に答える