2

ドロップダウンリストから州の住所を受け取る基本的な登録フォームを作成しようとしています。状態オブジェクトを含むモデルにドロップダウンからデータを抽出できないようです。以下に示すように、カスタム モデル バインダーを作成してみました。デバッグすると、ModelState は有効ですが、状態は常に null です。

モデル:

public class AccountInfo 
{
    public virtual Guid accoundID { get; set; }
    public virtual string city { get; set; }
    public virtual string email_address { get; set; }
    public virtual string fax_number { get; set; }
    public virtual string first_name { get; set; }
    public virtual string last_name { get; set; }
    public virtual string mailing_address { get; set; }
    public virtual string phone_number { get; set; }
    public virtual State state { get; set; }
    public virtual string zip_code { get; set; }
}
public class State
{
    public virtual int ID { get; set; }
    public virtual string text { get; set; }
    public virtual string value { get; set; }
}

モデル バインダー:

 public class StateModelBinder : IModelBinder
{
    private RepositoryDB Database;
    public object BindModel(
        ControllerContext controllerContext,
        ModelBindingContext bindingContext
        )
    {
        var key = bindingContext.ModelName + ".state";
        var value = bindingContext.ValueProvider.GetValue(key);
        if (value == null)
        {
            return null;
        }
        var result = new State();
        Database = new RepositoryDB(ConfigurationManager.
            ConnectionStrings["ConnectionString"].ConnectionString);

        try
        {
            var query = from s in Database.States
                        where s.value == value.ToString()
                        select new State()
                        {
                            text = s.text,
                            ID = s.ID,
                            value = s.value
                        };
            result = (State)query.ToList().ElementAt(0);        
        }
        catch (Exception ex)
        {
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex.Message);
            bindingContext.ModelState.SetModelValue(key, value);
        }


        return result;
    }

コントローラ:

[HttpPost]
    public ActionResult Index(AccountInfo accountModel)
    {
        try
        {
            if (ModelState.IsValid)
            {
                Database.Account.Add(accountModel);
                Database.SaveChanges();

                return Redirect(Url.Action("Success"));
            }
        }
        catch (Exception ex)
        {
            ModelState.AddModelError(String.Empty, ex);
        }
        // invalid info - return with error message         
        //repop select lists
        GetStates();
        return View(accountModel);
    }
public void GetStates()
    {
        IEnumerable<SelectListItem> states = from s in Database.States
                                                select new SelectListItem
                                                {
                                                    Text = s.text,
                                                    Value = s.value
                                                };

        ViewBag.state = states.ToList();
    }

意見:

@Html.LabelFor(model => model.state, "*State")
@Html.DropDownListFor(model => model.state, (IEnumerable<SelectListItem>)ViewBag.state)
4

1 に答える 1

3

これがあなたの問題です:

@Html.DropDownListFor(model => model.state, (IEnumerable<SelectListItem>)ViewBag.state)

複合型であるため、model.State へのバインディングは機能しません。

public class State
{
    public virtual int ID { get; set; }
    public virtual string text { get; set; }
    public virtual string value { get; set; }
}

考えてみると、フォームがポストバックする唯一のものは、完全なクラスではなく、「MN」(ミネソタ州) のような選択されたドロップダウン項目の値です。(各ドロップダウンリスト項目の値に「状態」クラスをシリアル化していません。うまくいけば、各状態の主キーだけです)モデルの状態を、その主キーのタイプに応じて文字列または整数にする必要がありますあなたの状態のように:

public class AccountInfo 
{
    //...
    public virtual string/int State { get; set; }
    //...
}

そこから、状態の一意の識別子 (たとえば、文字列または int としてサーバーに返される値である必要があります) から必要に応じて、State オブジェクトを再水和することができます。

于 2012-08-01T16:59:54.670 に答える