Я пытаюсь создать форму из такой модели:
class NewContractorModel
{
//...
public PhotoModel photos { get; set; }
//...
}
class PhotoModel
{
public List<Photo> f { get; set; }
}
Из контроллера я делаю некоторые манипуляции (на самом деле я удалил несколько фотографий из коллекции) на объекте модели и помещаю их на страницу просмотра, используя это:
return new View("SomeView", model);
Я пытался создать входные данные (скажем, скрытые входные) для каждой фотографии.
for (int i = 0; i < Model.photos.f.Count; ++i)
{
@Html.HiddenFor(m => m.photos.f[i].Uri)
@Html.HiddenFor(m => m.photos.f[i].ThumbnailUri)
@Html.HiddenFor(m => m.photos.f[i].SmallThumbnailUri)
@Html.TextBoxFor(m => m.photos.f[i].Description, new { placeholder = "Dodaj opis" })
}
Но, как я заметил, это не работает, потому что он отклоняет все модификации модели (он по-прежнему сохраняет все фотографии в списке, несмотря на то, что я удалил их в методе Controler).
Тогда я попробовал этот код:
for (int i = 0; i < Model.photos.f.Count; ++i)
{
Photo photo = Model.photos.f[i];
<input id="photos_f_@{@i}__Uri" name="photos.f[@{@i}].Uri" type="hidden" value="@photo.Uri"/>
<input id="photos_f_@{@i}__ThumbnailUri" name="photos.f[@{@i}].ThumbnailUri" type="hidden" value="@photo.ThumbnailUri"/>
<input id="photos_f_@{@i}__SmallThumbnailUri" name="photos.f[@{@i}].SmallThumbnailUri" type="hidden" value="@photo.SmallThumbnailUri"/>
<input id="photos_f_@{@i}__Description" name="photos.f[@{@i}].Description" placeholder="Dodaj opis" type="text" value="@photo.Description"/>
}
... и на этот раз ЭТО РАБОТАЕТ!
Может кто-нибудь объяснить мне, в чем разница между этими двумя частями кода?
Я пытался использовать этот код более десяти раз, и он всегда работает одинаково, поэтому я не виноват. ;)
Я думаю, что есть ошибка в методах HtmlHelper, но есть ли обход? Я хотел бы использовать вспомогательные методы вместо необработанного HTML.
EDIT:
Это упрощенный класс контроллера.
public class MyController
{
private NewContractorModel _model = null;
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
_model = SerializationUtility.Deserialize(Request.Form["Data"]) as NewContractorModel;
if (_model == null)
_model = TempData["Data"] as NewContractorModel;
if (_model == null)
_model = new NewContractorModel() as NewContractorModel;
TryUpdateModel(_model);
}
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (filterContext.Result is RedirectToRouteResult)
TempData["Data"] = _model;
}
private bool CheckModel(object model)
{
Type type = model.GetType();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo p in properties)
{
object[] attr = p.GetCustomAttributes(true);
foreach (object a in attr)
{
if (a is ValidationAttribute)
{
object value = p.GetValue(model, null);
if (!((ValidationAttribute)a).IsValid(value))
return false;
}
}
}
return true;
}
protected ActionResult SelectPage(string delPhoto)
{
if (!CheckModel(_model))
{
// Do some action
}
//.....
foreach (ZAY.Database.Photo p in _model.photos.f)
{
if (p.Uri == Request["delPhoto"])
{
_model.photos.f.Remove(p);
break;
}
}
//.....
return View("SomeView", _model);
}
}
Я заметил, что внутри лямбды модель выглядит так же, как после вызова TryUpdateModel (до внесения изменений). Если я не использую лямбды, модель модифицируется ...: /
А также мой класс Photo (сгенерированный из EntityFramework - так что ничего интересного), а также упрощенный:
public class Photo : EntityObject
{
[Required]
public string Uri { get; set; }
[Required]
public string ThumbnailUri { get; set; }
[Required]
public string SmallThumbnailUri { get; set; }
public string Description { get; set; }
}
Извините, что пишу только такие маленькие фрагменты, но весь код более сложный - есть только самая интересная часть.