从View到控制器传递模型值不起作用

时间:2013-02-03 17:12:15

标签: asp.net asp.net-mvc asp.net-mvc-3 razor

我的模型有两个属性,其中一个是另一个类的对象

  public class Association : Entity
{
    public Association()
    {
        this.User = new User();
    }

    public User User
    {
        get;
        set;
    }

    public Role Role
    {
        get;
        set;
    }
};

我的视图强烈输入此模型

@model MuddyBoots.Greenlight.Association
.
.
@using (Html.BeginForm())
{

@Html.ValidationSummary(true)
    <div>
     @Html.TextBoxFor(model => model.User.FirstName,new { id = "first-name" })
    <span class="red-asterisk">@Html.ValidationMessageFor(model =>    model.User.FirstName)</span>
 </div>
   <div>
    @Html.HiddenFor(model => model.Role, new { id="hiddenRole"})
        <ul id="user-roles">
            <li><input type="radio" name="user-role" id="role-admin" value="01" checked="checked" /> Read only</li>
            <li><input type="radio" name="user-role" id="role-member" value="02" /> Restricted</li>
            <li><input type="radio" name="user-role" id="role-read" value="03"/> Standard</li>
            <li><input type="radio" name="user-role" id="role-subscriber" value="04" /> Administrator</li>
        </ul>
</div>
}

我的控制器功能是这样写的:

[HttpPost]
    public ActionResult AddUser(Association association)
    {
        string firstName = association.User.FirstName;
        var role = association.Role;

         IRepository<Association> associationRepository = new IRepository<Association>(db);
        if (ModelState.IsValid)
        { 
           siteRepository.Update(site);
            return RedirectToAction("Index");
        }
        return View(association);
    }

我的问题是:当我发布我的视图时,我的关联对象为null,它没有值。

更准确地说,当我尝试调试这两行时:

 string firstName = association.User.FirstName;
 var role = association.Role;    

它们的值为null,但如果我对第一行进行注释,则角色变量具有值。所以感觉问题与User属性有关,但我不知道如何解决它。

2 个答案:

答案 0 :(得分:3)

您似乎在角色类型中使用了一些隐藏字段:

@Html.HiddenFor(model => model.Role, new { id = "hiddenRole" })

但是Role属性是一个复杂类型,您不能将其序列化为隐藏字段。您必须为要发送的每个属性使用隐藏字段:

@Html.HiddenFor(model => model.Role.Property1)
@Html.HiddenFor(model => model.Role.Property2)
@Html.HiddenFor(model => model.Role.Property...)

此外,您似乎在表单中使用了一些名为user-role的单选按钮,但您的Role类上没有具有此名称的属性(您不能在属性名称中使用破折号),所以我猜如果您希望将这些单选按钮的值绑定到Association模型上Role类的某些属性,则必须在此处使用正确的名称。

例如,假设您的Role类看起来像这样:

public class Role
{
    public string Value { get; set; }
}

现在您的视图可能如下所示:

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <div>
        @Html.TextBoxFor(model => model.User.FirstName, new { id = "first-name" })
        <span class="red-asterisk">
            @Html.ValidationMessageFor(model => model.User.FirstName)
        </span>
    </div>
    <div>
        <ul id="user-roles">
            <li>
                @Html.RadioButtonFor(model => model.Role.Value, "01", new { id = "role-admin" }) 
                Read only
            </li>
            <li>
                @Html.RadioButtonFor(model => model.Role.Value, "02", new { id = "role-member" }) 
                Restricted
            </li>
            <li>
                @Html.RadioButtonFor(model => model.Role.Value, "03", new { id = "role-read" }) 
                Standard
            </li>
            <li>
                @Html.RadioButtonFor(model => model.Role.Value, "04", new { id = "role-subscriber" }) 
                Administrator
            </li>
        </ul>
    </div>

    <button type="submit">OK</button>
}

答案 1 :(得分:1)

我认为ModelBinder不会绑定子对象。您可以创建一个自定义ModelBinder来绑定您的Association类,或者只创建一个ViewModel类,将您当前的Model展平为一个类。所以你的AssociationViewModel模型类可能如下所示:

public class AssociationViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string RoleName { get; set; }
}


public ActionResult AddUser(AssociationViewModel associationViewModel)
{
    if (ModelState.IsValid)
    { 
        var association = new Association
        {
            User.FirstName = associationViewModel.FirstName,
            Role = new Role { Name = associationViewModel.RoleName }
        };

        IRepository<Association> associationRepository = new IRepository<Association>(db);
        ....
    }
 }