Asp.Net MVC 4 - привязка к сложному объекту, не работающему в POST
У меня есть модель вида, которая выглядит так:
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 });
}
Может кто-нибудь сказать мне, что я сделал не так, пожалуйста?
2 ответа
Пользовательская привязка решила проблему. Спасибо всем за полезные комментарии.
Брэд Кристи отметил, что, поскольку объект, с которым мое действие пытается связать, имеет только частный конструктор, потребуется специальная привязка.
Пользовательская привязка:
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});
}
Замените цикл foreach на цикл for, как показано ниже
@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>
}