2

我有一个看起来像这样的视图模型:

 public class EventVm
    {
        public int Id { get; set; }
        public int GroupId { get; set; }
        public string Title { get; set; }       
        public EventLayout EventLayout { get; set; }
    }

EventLayout 是一个自定义对象,如下所示:

public class EventLayout
{
    private const string SingleColumnLayoutLocalKey = "MyOrg.SingleColumnLayout";
    ...
    //Removed for breviety

    public static EventLayout SingleColumnLayout = new EventLayout(SingleColumnLayoutLocalKey);
    ...
    //Removed for breviety

    public string Value
    {
        get { return _layoutLocalKey; }
    }

    private readonly string _layoutLocalKey;

    private EventLayout(string layoutLocalKey)
    {
        _layoutLocalKey = layoutLocalKey;
    }

    public static EventLayout LayoutFromLocalString(string localString)
    {
       ...
    }

    public override string ToString()
    {
        return _layoutLocalKey;
    }

    public override bool Equals(object obj)
    {
        if (obj.GetType() != this.GetType())
        {
            return false;
        }
        if (this._layoutLocalKey == obj.ToString())
        {
            return true;
        }
        return false;
    }

    public override int GetHashCode()
    {
        return this._layoutLocalKey.GetHashCode();
    }
}

基本上 EventLayout 只是一个提供字符串后备存储的自定义枚举。EventLayout 绑定到一个 Select 表单控件(T() 只是一个本地化扩展方法):

<select id="eventLayoutSelect" name="EventVm.EventLayout">
    @foreach (var option in Model.EventLayoutOptions)
    {
        <option value="@option.Value" @((Model.EventLayout != null && Model.EventLayout.Equals(option))
                                            ? "selected=selected" 
                                            : string.Empty)>@T(option.Value)</option>
    }
</select>

当我将此表单发布到服务器时,当操作尝试绑定时,EventVm.EventLayout 属性为空。但是我可以看到在表单数据中发布了一个 EventLayout 实例:

在此处输入图像描述

我的动作是这样的:

 [HttpPost]
    public ActionResult Update(EventVm eventVm)
    {
        _eventService.UpdateEvent(eventVm);
        return RedirectToAction("Index", new { groupId = eventVm.GroupId }); 
    }

有人可以告诉我我做错了什么吗?

4

2 回答 2

1

自定义绑定解决了这个问题。谢谢大家的有用意见。

Brad Christie 指出,因为我的操作尝试绑定的对象只有一个私有构造函数,所以需要自定义绑定。

自定义绑定:

public class EventVmBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {

        HttpRequestBase request = controllerContext.HttpContext.Request;

        var eventVm = new EventVm()
        {
            Id = Int32.Parse(request.Form.Get("Id")),
            GroupId = Int32.Parse(request.Form.Get("GroupId")),
            Title = request.Form.Get("Title"),
            HeaderMarkup = request.Form.Get("HeaderMarkup"),
            LeftNavigationMarkup = request.Form.Get("LeftNavigationMarkup"),
            CenterContentMarkup = request.Form.Get("CenterContentMarkup"),
            RightNavigationMarkup = request.Form.Get("RightNavigationMarkup"),
            EventLayout = EventLayout.LayoutFromLocalString(request.Form.Get("EventLayout")),
            DisplayOrder = Int32.Parse(request.Form.Get("DisplayOrder")),
            Active = request.Form.Get("Active").As<bool>(),
            CanEdit = request.Form.Get("CanEdit").As<bool>()
        };

        return eventVm;
    }

}

在动作中接线:

 [HttpPost]
    public ActionResult Create([ModelBinder(typeof(EventVmBinder))]EventVm eventVm)
    {
        _groupService.AddEventToGroup(eventVm);
        return RedirectToAction("Index", new {groupId = eventVm.GroupId});
    }
于 2014-02-05T21:35:03.230 回答
0

用 for 循环替换你的 foreach 循环,如下所示

@foreach (var option in Model.EventLayoutOptions)
{
<option value="@option.Value" @((Model.EventLayout != null && Model.EventLayout.Equals(option))
                                        ? "selected=selected" 
                                        : string.Empty)>@T(option.Value)</option>
}  

for(int i=0; i<Model.EventLayoutOptions.Count; i++ )
{
<option value="@Model.EventLayoutOptions[i].Value" @((Model.EventLayout != null &&      Model.EventLayout.Equals(Model.EventLayoutOptions[i]))
                                        ? "selected=selected" 
                                        :  string.Empty)>@T(Model.EventLayoutOptions[i].Value)</option>
}
于 2014-05-20T22:16:07.090 回答