Он видит, как некоторые думают, что даже в MVC 3 входные параметры не могут быть динамическим
Я так думаю. Давайте посмотрим на указанном примере:
[HttpPost]
[ValidateInput(false)]
public virtual ActionResult Update(dynamic editorModel) {
if (!TryUpdateModel(_model, "CurrentModel")) {
var parentId = _model.Parent != null ? (string)_model.Parent.Id : null;
var viewModel = new EditViewModel
{
RootModel = _session.Query<IPageModel>()
.Where(model => model.Parent == null)
.SingleOrDefault(),
CurrentModel = _model,
ParentModel = parentId != null ? _session.Load<IPageModel>(parentId) : null,
};
return View("edit", viewModel);
}
UpdateModel(_model);
_model.Metadata.Changed = DateTime.Now;
_model.Metadata.Published = _model.Metadata.IsPublished ? DateTime.Now : default(DateTime?);
_model.Metadata.ChangedBy = HttpContext.User.Identity.Name;
_repository.SaveChanges();
_repository.Refresh(_model);
var page = _model as IPageModel;
if (page.Parent != null) {
_model = _repository.SingleOrDefault<IPageModel>(m => m.Id == page.Parent.Id);
}
return RedirectToAction("index", new { model = _model });
}
Можете ли вы указать мне, как/где именно эта editorModel
динамическая переменная, используемая внутри этого действия контроллера?
И чтобы еще больше упростить это действие контроллера, оно работает, потому что никогда не использует динамическую переменную, переданную как аргумент. Я упростил ее, чтобы лучше проиллюстрировать то, что это действие примерно делает относительно модели связывания (выбрасывание конечно весь шум инфраструктуры, что мы не заинтересованы в здесь, чтобы проиллюстрировать эту проблему):
[HttpPost]
public ActionResult Update(dynamic blablabla)
{
dynamic model = new MyViewModel();
UpdateModel(model);
// at this stage the model will be correctly bound
return View(model);
}
Внутри этой акции TryUpdateModel
и UpdateModel
методы вызываются в переменной экземпляра _model
, которая передается в конструкторе и имеет тип IPageModel
. ASP.NET MVC, возможно, не знает (без настраиваемого связующего устройства, конечно) тип вашего аргумента динамического действия. Просто запустите этот код, поместите контрольную точку внутри действия Update
и наблюдайте тип переменной editorModel
. Это будет просто System.Object
. Нет чудес.
Так что для меня совершенно нормально, что это работает так же в ASP.NET Web API.
Большое спасибо за отличное объяснение, и я прошу прощения за пугающий вопрос. Если бы я хотел иметь базовый класс, пользователь, который является абстрактным, а затем классом администратора, который наследует класс User, какова ваша рекомендация, если я хотел бы использовать контроллер API для сохранения всех пользователей? Является ли это обычным связующим устройством? Другой вопрос - UpdateModel, это не существует в контроллере api, так как это означает обновление существующего объекта? – Marcus
@Marcus, в ASP.NET Web API вы можете написать пользовательский 'MediaTypeFormatter' для достижения этой задачи. Вот [пример] (http://code.msdn.microsoft.com/Using-JSONNET-with-ASPNET-b2423706), который использует JSON.NET в качестве сериализатора. А с JSON.NET вы можете написать ['custom JsonConverter'] (http://stackoverflow.com/a/8031283/29407), который позволит вам сериализовать абстрактные классы. –
Мой вопрос больше о сохранении и обновлении пользователя, который имеет тип, наследующий от класса User. Посмотрите на этот пример http://pastebin.com/sRGW62yw Конечно, входной параметр не может быть пользователем, поскольку он не имеет свойства LastName, и тогда он не будет связывать его, потому что он не существует. Вот почему я попытался использовать динамический входной параметр, потому что единственное, что я знаю, это то, что входной параметр расширяет класс User, и я хочу сохранить все данные из расширенного класса. Надеюсь, вы понимаете, что я здесь делаю. – Marcus