1

コントローラーがポストバックのサブクラス モデルを認識するのに問題があります。

データベースに格納されたフィールド メタ データを使用して、動的な Web フォームを作成しています。私のViewModelには、2つの親タイプがあります

public class Form
{
    public List<Question> Questions { get; set; }
}
public class Question
{
    public string QuestionText { get; set; }
}

および Question のサブクラス

public class TextBoxQuestion : Question
{
    public string TextAnswer { get; set; }
    public int TextBoxWidth { get; set; }
}

また、フォーム タイプをモデルとして使用するビューと、2 つの表示テンプレート (1 つは質問用、もう 1 つはフォーム TextBoxQuestion 用) を使用するビューもあります。

//Views/Form/index.cshtml
@model Form
@Html.DisplayFor(m => m.Questions)

-

//Views/Shared/DisplayTemplates/Question.cshtml
@model Question
@if(Model is TextBoxQuestion)
{
    @Html.DisplayForModel("TextBoxQuestion")
}

-

//Views/Shared/DisplayTemplates/TextBoxQuestion.cshtml
@model TextBoxQuestion
<div>
    @Model.QuestionText
    @Html.TextBoxFor(m => m.TextAnswer)
</div>

ページが読み込まれると、コントローラーは TextBoxQuestion のインスタンスを作成し、それを Question コレクションに追加して、Form オブジェクトをビューに渡します。すべてが機能し、テキストボックスがページに表示されます。

しかし、コントローラーにポストバックすると、コードは質問を TextBoxQuestion として認識しません。親タイプの質問としてのみ認識されます。

[HttpPost]
public ActionResult Index(Form f)
{
    foreach (var q in f.Questions)
    {
        if (q is TextBoxQuestion)
        {
            //code never gets here
        }
        else if (q is Form)
        {
            //gets here instead
        }
    }
}

足りないものはありますか?

4

2 に答える 2

1

モデル バインダーは、メソッドが期待する型のインスタンスを作成します。この方法でサブクラスと表示テンプレートを使用する場合は、独自のモデル バインダーを作成する必要があります。

TextBoxQuestionまたはQuestionが投稿されているかどうかを判断するために、1 つまたは複数の属性の存在を確認することをお勧めします。

モデルバインダー:

public class QuestionModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Question result;
        ValueProviderResult text = bindingContext.ValueProvider.GetValue("TextAnswer");
        if (text != null) // TextAnswer was submitted, we'll asume the user wants to create a TextBoxAnswer
            result = new TextBoxQuestion { TextAnswer = text.AttemptedValue /* Other attributes */ };
        else
            result = new Question();

        // Set base class attributes
        result.QuestionText = bindingContext.ValueProvider.GetValue("QuestionText").AttemptedValue;
        return result;
    }
}

次に、Global.asax.cs に接続します。

ModelBinders.Binders.Add(typeof(Question), new QuestionModelBinder());
于 2012-11-13T20:12:04.190 に答える
0

一度に 1 つの質問をしているように見えます。したがって、情報を投稿するときは、質問の集まりではなく、1 つだけを送信している可能性が最も高いです。メソッドを次のように変更します。

[HttpPost]
public ActionResult Index(Question q)
{
    if (q is TextBoxQuestion)
    {
        //proces TextBoxQuestion
    }
    else if (q is Question)
    {
        //process generic question
    }
}
于 2012-11-13T19:24:52.590 に答える