Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc TryUpdateModel未按预期工作_Asp.net Mvc_Asp.net Mvc 3 - Fatal编程技术网

Asp.net mvc TryUpdateModel未按预期工作

Asp.net mvc TryUpdateModel未按预期工作,asp.net-mvc,asp.net-mvc-3,Asp.net Mvc,Asp.net Mvc 3,我正在从事一个ASP.NET MVC项目,该项目将允许用户对对象的属性执行批量编辑。实现是一种类似“向导”的形式,流程分为四个阶段,如下所示: “选择要编辑的属性”-第一页将向用户显示一个复选框列表,代表他们要编辑的每个属性。用户应检查他们希望编辑的属性并选择“继续” “编辑所选属性”-第二页将向用户显示不同的“编辑器”列表,这些“编辑器”对于他们在第一页上选择的每个属性都是唯一的 “查看您的更改”-此页面将允许用户查看他们对所选属性所做的更改 “提交更改”-此页面将实际提交有关用户希望针对选定

我正在从事一个ASP.NET MVC项目,该项目将允许用户对对象的属性执行批量编辑。实现是一种类似“向导”的形式,流程分为四个阶段,如下所示:

  • “选择要编辑的属性”-第一页将向用户显示一个复选框列表,代表他们要编辑的每个属性。用户应检查他们希望编辑的属性并选择“继续”
  • “编辑所选属性”-第二页将向用户显示不同的“编辑器”列表,这些“编辑器”对于他们在第一页上选择的每个属性都是唯一的
  • “查看您的更改”-此页面将允许用户查看他们对所选属性所做的更改
  • “提交更改”-此页面将实际提交有关用户希望针对选定对象集合对选定属性所做编辑的信息
  • 相当直截了当

    正如我提到的,“编辑器”对于每个属性都是唯一的,并且可以有不同控件的任意组合。一旦用户进行了编辑,并且应用程序将这些信息发布到“审阅”页面,我就遇到了问题

    我们开发了一个“EditorWorker”类的概念,该类对每个属性都是唯一的,它负责生成每个编辑器所需的ViewModel,但也负责创建/返回(在“Review”页面控制器操作中)一个对象,该对象是post数据可以绑定到的编辑器的“model”对象,然后可以使用它显示编辑的数据以供查看。此对象的属性应与编辑器中控件的ID匹配,以便可以进行模型绑定

    我已经让“EditorWorker”创建并返回了所需的类,但由于某种原因,当我调用
    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;
    }