gpt4 book ai didi

asp.net-mvc - TryUpdateModel无法按预期工作

转载 作者:行者123 更新时间:2023-12-04 22:00:28 25 4
gpt4 key购买 nike

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


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


非常坦率的。

正如我提到的,“编辑器”对于每个属性都是唯一的,并且可以具有不同控件的任意组合。用户进行修改后,应用程序将该信息发布到“查看”页面上,这是我当前遇到的问题。

我们已经开发了每个属性都唯一的“ EditorWorker”类的概念,该类负责生成每个编辑器所需的ViewModel,但也负责创建/返回(在“ Review”页面控制器操作内)对象,该对象是发布数据可以绑定到的编辑器的“模型”对象,然后可以用于显示编辑后的数据以供查看。该对象应具有与编辑器中的控件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; }
}


我完全理解,此控制器操作在当前状态下是不完整的。我目前正在尝试继续前进之前正确填充那些EditData对象。如前所述,任何想法将不胜感激。谢谢。

更新:关于@mare的评论,对不起,我应该更清楚地解释这一部分。对TryUpdateModel的调用实际上返回的是true,但是传递给模型对象的模型对象上的字段实际上并未从已过帐表单数据中已确认的值中填充。传递给调用的模型对象不是列表,而是poco。然后将最终最终希望填充的模型对象添加到模型对象的列表集合中,然后将这些列表对象用于显示发布的数据以在“审阅”页面上进行审阅。我根本没有从数据存储中加载任何东西。每个选定属性的唯一编辑器都将呈现到“编辑”屏幕,并且在将批量编辑提交给服务之前,我试图捕获编辑值以显示在“审阅”屏幕上。希望这更加清楚。谢谢。

更新2:我已在注释中包括@mare请求的 ReviewBatchViewModel类的定义。在大多数情况下,在此代码示例中使用 var关键字主要是由于以下事实:填充这些变量的方法将为所选的每个属性返回不同类型的对象,因此我永远无法确切知道它在运行时的状态(尽管它将始终实现一个接口,在这种情况下为 IEditorWorker和/或 IEditData)。模型中只有一个称为“属性”的类。提供的代码示例具有与该类有关的三个变量:1) SelectedAttributeIds是用户选择编辑的属性的ID的逗号分隔列表,该列表通过隐藏字段从“编辑”页面传递到“审阅”页面,2) selectedAttributes是与我可以使用的ID相对应的实际Attribute对象的集合,以及3) attributeEditData是我尝试使用的每个给定属性的 IEditData类的实例绑定从“编辑”页面发布的数据。

希望这些附加信息可以使您的工作更加顺利。

最佳答案

TryUpdateModel是通用方法,因此尝试基于Generic Type Parameter推断所有类型信息。

根据我在上面的示例中所了解的,您总是传递IEditData正确吗?

实际上,您是在说:

TryUpdateModel<IEditData>(attributeEditData)


这很可能是没有看到设置任何属性的原因,因为 IEditData没有任何属性;)

要执行您想要的操作,您可能必须创建一个 custom ModelBinder

作为快速代码回顾的注释,您的解决方案似乎过于复杂。我不得不盯着你的解决方案好一会儿,才弄清楚从哪里开始。创建自定义模型联编程序可能会解决您眼前的问题,但是您可能会在这里遇到大量维护麻烦的问题。我愿意打赌,有一种更简单的方法可以减少以后的问题。

根据您的评论,我将代码从System.Object更改为IEditData接口,但是一切仍然保留。我在前面提到的使用var的注释中注意到,因为直到运行时才知道类型。但是,var关键字没有任何魔术。它唯一要做的就是为您提供隐式键入,但是它仍然是静态键入的。

关于MVC的好处是,您可以跳到Codeplex并查看 TryUpdateModel的源代码。深入研究几层,您最终会找到对此内部方法的调用:

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;
}


请注意,在任何情况下都使用 typeof(TModel) ...在您的情况下,它已转换为 typeof(IEditData),这并不是很有用,因为它只是一个标记接口。您应该能够修改此代码以供自己使用,并确保使用 GetType()以便在运行时获取实际的类型。

希望这对您有所帮助!

附言我在上面的代码中添加了一些注释,以提供一些帮助

关于asp.net-mvc - TryUpdateModel无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4833543/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com