Asp.net mvc TryUpdateModel未按预期工作
我正在从事一个ASP.NET MVC项目,该项目将允许用户对对象的属性执行批量编辑。实现是一种类似“向导”的形式,流程分为四个阶段,如下所示:Asp.net mvc TryUpdateModel未按预期工作,asp.net-mvc,asp.net-mvc-3,Asp.net Mvc,Asp.net Mvc 3,我正在从事一个ASP.NET MVC项目,该项目将允许用户对对象的属性执行批量编辑。实现是一种类似“向导”的形式,流程分为四个阶段,如下所示: “选择要编辑的属性”-第一页将向用户显示一个复选框列表,代表他们要编辑的每个属性。用户应检查他们希望编辑的属性并选择“继续” “编辑所选属性”-第二页将向用户显示不同的“编辑器”列表,这些“编辑器”对于他们在第一页上选择的每个属性都是唯一的 “查看您的更改”-此页面将允许用户查看他们对所选属性所做的更改 “提交更改”-此页面将实际提交有关用户希望针对选定
TryUpdateModel
并传入该类时,它的属性并没有像我所期望的那样由于该方法调用而填充。我已验证这些值是否在已发布的FormCollection中。下面是我尝试执行此操作的控制器操作的代码。如果有人能帮助我理解为什么TryUpdateModel
在这种情况下不起作用,我将非常感激
[HttpPost]
public virtual ActionResult Review(ReviewBatchViewModel model)
{
var selectedAttributes = GetSelectedAttributes(model.SelectedAttributeIds.Split(',').Select(i => Int64.Parse(i)).ToArray());
var workers = new List<IEditorWorker>();
var reviewData = new Dictionary<ViewAttribute, IEditData>();
foreach (var attribute in selectedAttributes)
{
if (!string.IsNullOrEmpty(attribute.EditorWorker)) // If there is no EditorWorker defined for this object, move on...
{
var worker = ServiceLocator.Current.GetInstance(Type.GetType(string.Format("{0}.{1}", EditorWorkerNamespace, attribute.EditorWorker)));
var attributeEditData = ((IEditorWorker)worker).LoadEditData();
if (TryUpdateModel(attributeEditData))
model.EditData.Add(attributeEditData); // model.EditData is a List<IEditData> that will be iterated on the Review page
reviewData.Add(attribute, attributeEditData);
}
}
return View(model);
}
// ReviewBatchViewModel.cs
public class ReviewBatchViewModel : BaseViewModel
{
public ReviewBatchViewModel() { EditData = new List<IEditData>(); }
public string SelectedAttributeIds { get; set; }
public List<ViewAttribute> SelectedAttributes { get; set; }
public List<IEditData> EditData { get; set; }
}
// IEditData.cs
public interface IEditData
{
}
// BroadcastStatusEditData.cs
public class BroadcastStatusEditData : IEditData
{
public int BroadcastStatus { get; set; }
}
[HttpPost]
公共虚拟操作结果审核(ReviewBatchViewModel)
{
var selectedAttributes=GetSelectedAttributes(model.SelectedAttributeIds.Split(',).Select(i=>Int64.Parse(i)).ToArray();
var workers=新列表();
var reviewData=新字典();
foreach(selectedAttribute中的var属性)
{
如果(!string.IsNullOrEmpty(attribute.EditorWorker))//如果没有为此对象定义EditorWorker,请继续。。。
{
var-worker=ServiceLocator.Current.GetInstance(Type.GetType(string.Format(“{0}.{1}”,EditorWorkerNamespace,attribute.EditorWorker));
var attributeEditData=((IEditorWorker)worker.LoadEditData();
if(TryUpdateModel(attributeEditData))
model.EditData.Add(attributeEditData);//model.EditData是将在审阅页面上迭代的列表
添加(属性,attributeEditData);
}
}
返回视图(模型);
}
//ReviewBatchViewModel.cs
公共类ReviewBatchViewModel:BaseViewModel
{
public ReviewBatchViewModel(){EditData=new List();}
公共字符串SelectedAttribute ID{get;set;}
公共列表SelectedAttribute{get;set;}
公共列表EditData{get;set;}
}
//IEditData.cs
公共接口IEditData
{
}
//BroadcastStatusEditData.cs
公共类BroadcastStatusEditData:IEditData
{
公共int广播状态{get;set;}
}
我完全理解控制器操作在其当前状态下是不完整的。我目前正在努力在继续之前正确填充这些EditData对象。如前所述,如有任何想法,将不胜感激。谢谢
更新:关于@mare的评论,我应该更清楚地解释这一部分,对不起。对TryUpdateModel的调用实际上返回true,但是传递给它的模型对象上的字段实际上并没有根据已确认存在于已发布表单数据中的值填充。传递到调用中的模型对象不是列表,它只是一个poco。最终生成的、希望最终填充的模型对象将被添加到模型对象的列表集合中,然后该列表集合将用于在“审阅”页面上显示要审阅的已发布数据。我根本没有从数据存储中加载任何内容。每个选定属性的唯一编辑器将呈现到编辑屏幕上,我正在尝试捕获编辑值,以便在将批量编辑提交到服务之前显示在审阅屏幕上。希望这更清楚。谢谢
更新2:我已经按照@mare的要求在评论中包含了ReviewBatchViewModel
类的定义。在本代码示例的大多数情况下,使用var
关键字主要是因为填充这些变量的方法将为每个选定的属性返回不同类型的对象,因此我永远不知道在运行时它将是什么(尽管它总是实现一个接口,但在这种情况下,IEditorWorker
和/或IEditData
)。模型中有一个名为“Attribute”的类。提供的代码示例有三个与该类相关的变量:1)selectedAttributes
是用户选择编辑的属性Id的逗号分隔列表,它通过隐藏字段从编辑页面传递到查看页面,2)selectedAttributes
是与我可以使用的Id相对应的实际属性对象的集合
TryUpdateModel<IEditData>(attributeEditData)
protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider) where TModel : class {
if (model == null) {
throw new ArgumentNullException("model");
}
//valueProvider is passed into this internal method by
// referencing the public ControlerBase.ValueProvider property
if (valueProvider == null) {
throw new ArgumentNullException("valueProvider");
}
Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties);
//Binders is an internal property that can be replaced by
// referencing the static class ModelBinders.Binders
IModelBinder binder = Binders.GetBinder(typeof(TModel));
ModelBindingContext bindingContext = new ModelBindingContext() {
Model = model,
ModelName = prefix,
ModelState = ModelState,
ModelType = typeof(TModel),
PropertyFilter = propertyFilter,
ValueProvider = valueProvider
};
binder.BindModel(ControllerContext, bindingContext);
return ModelState.IsValid;
}