我正在开发一个ASP.Net MVC 3项目,其中很多非常简单的实体只需要来自Administrative界面的基本CRUD支持。所有这些实体都有一个带有Id,Name的简单域对象,并且为此目的有一个抽象基类NamedEntity
。
我有一个基本的控制器NamedEntityController<T> where T : NamedEntity
可以处理简单的crud操作,其所有方法都是虚拟的。有一个很好的小NamedEntityCreateOrUpdateModel<T>
用于传回数据&amp;发表意见。
现在我有一个名为NamedEntity
的{{1}}的特定子类,它具有其他属性,特别是与其他主题具有父/子关系,因此我们需要捕获父对象的整数Id这对其他Topic
操作毫无意义。为此,我将子类化为NamedEntity
和TopicsController: NamedEntityController<Topic>
(在任何人咬住我的脑袋之前,所有真正的工作都是在任务层完成的,我只是在这里简化问题描述。)
基本控制器定义
TopicCreateOrUpdateModel : NamedEntityCreateOrUpdateModel<Topic>
子类定义
[HttpPost]
public virtual ActionResult Edit(NamedEntityCreateOrEditModel<T> Model)
{ ... }
(为简洁起见未显示:Edit的“获取”版本为每个正确设置了基本[HttpPost]
public override ActionResult Edit(NamedEntityCreateOrEditModel<Topic> Model)
{
TopicCreateOrEditModel tm = Model as TopicCreateOrEditModel;
...
}
或特定于主题的子类,并在该模型上返回NamedEntityCreateOrEditModel
。)
我可以从调试断点中清楚地看到,正在调用子类的Edit(post)方法。但是上面显示的演员总是导致View()
,从而击败了子类的点。
如果我尝试创建
null
MVC抱怨说,新方法和基类方法之间的操作不明确。
这个问题有一个简单的解决方案吗?在这种情况下,我可以完全绕过基类控制器/模型,并且基本上说'如果你需要除了简单的字段之外的其他字段,不要继承',但这似乎非常错误,特别是因为域对象继承。
答案 0 :(得分:1)
在Action中明确使用TryUpdateModel
,您可以删除参数并使签名相同。这允许使用override
关键字,如下所示:
public class A { }
public class B : A { }
public class AController {
[HttpPost]
public virtual ActionResult Edit() {
A a = new A();
TryUpdateModel<A>(a);
if (ModelState.IsValid)
a.save();
}
}
public class BController : AController {
[HttpPost]
public override ActionResult Edit() {
B b = new B();
TryUpdateModel<B>(b);
if (ModelState.IsValid)
b.save();
}
}
这为我修复了AmbiguousMethodException,并调用了正确路由的Edit
个动作。但是,可能存在我不知道的安全问题。
答案 1 :(得分:0)
当您的子类“编辑”被调用时,它是通过NamedEntityCreateOrEditModel<Topic>
还是TopicCreateOrEditModel
?前者会使演员失败(不用说,你可以将派生类强制转换为基础,但反之亦然)。
答案 2 :(得分:0)
显然,MVC传递的是NamedEntityCreateOrEditModel<Topic>
而不是TopicCreateOrEditModel
的实例。由于在这种情况下我无法看到Edit
的多态性值,我想明确将其标记为new
应该没问题(是的,这是一个黑客攻击)。
[HttpPost]
public new ActionResult Edit(TopicCreateOrEditModel Model) { ... }
更正统的方法可能是为NamedEntityCreateOrEditModel<Topic>
类型编写自定义模型绑定器,以便在当前控制器为TopicCreateOrEditModel
的情况下构建TopicsController
的实例。
或者,对您当前使用的继承一无所知,只需删除Edit
中的NamedEntityController<T>
(以及类似的CRUD方法),因为我无法看到它的值。如果你有充分的理由存在它,请忽略这个建议。