.net 具有子类模型的子类控制器
我正在从事一个ASP.NETMVC3项目,其中许多非常简单的实体只需要从管理界面获得基本的CRUD支持。所有这些实体都有一个Id为Name的简单域对象,并且有一个抽象基类.net 具有子类模型的子类控制器,.net,asp.net-mvc,asp.net-mvc-3,.net,Asp.net Mvc,Asp.net Mvc 3,我正在从事一个ASP.NETMVC3项目,其中许多非常简单的实体只需要从管理界面获得基本的CRUD支持。所有这些实体都有一个Id为Name的简单域对象,并且有一个抽象基类NamedEntity 我有一个基本的控制器,NamedEntityController,其中T:NamedEntity可以处理简单的crud操作,其所有方法都是虚拟的。有一个很好的NamedEntityCreateOrUpdateModel,用于将数据来回传递给视图 现在我有了一个名为NamedEntity的特殊子类Topic
NamedEntity
我有一个基本的控制器,NamedEntityController,其中T:NamedEntity
可以处理简单的crud操作,其所有方法都是虚拟的。有一个很好的NamedEntityCreateOrUpdateModel
,用于将数据来回传递给视图
现在我有了一个名为NamedEntity
的特殊子类Topic
,它有额外的属性,特别是与其他主题有父/子关系,因此我们需要捕获父类的整数Id,它对其他NamedEntity
操作没有意义。为此,我将子类化为TopicsController:NamedEntityController
和TopicCreateOrUpdateModel:NamedEntityCreateOrUpdateModel
(在任何人攻击我之前,所有真正的工作都是在任务层完成的,我只是在这里简化问题描述。)
基本控制器定义
[HttpPost]
public virtual ActionResult Edit(NamedEntityCreateOrEditModel<T> Model)
{ ... }
MVC抱怨新方法和基类方法之间的操作不明确
这个问题有简单的解决办法吗?在这种情况下,我可以完全绕过基类控制器/模型,基本上说‘如果您需要简单字段以外的其他字段,请不要继承’,但这似乎是非常错误的,特别是因为域对象正在继承。当您的子类“Edit”被调用时,它是否正在传递
NamedEntityCreateOrEditModel
或TopicCreateOrEditModel
?前者将使强制转换失败(不用说,您可以将派生类强制转换为它的基类,但反之亦然)。当调用子类的Edit时,是将其传递给NamedEntityCreateOrEditModel
还是TopicCreateOrEditModel
?前者将使强制转换失败(不用说,您可以将派生类强制转换为它的基类,但反之亦然)。显然,MVC传递的是NamedEntityCreateOrEditModel
的实例,而不是TopicCreateOrEditModel
。在这种情况下,由于我看不到Edit
的多态性值,所以我想明确地将其标记为new
应该可以(是的,这是一个hack)
更传统的方法可能是为NamedEntityCreateOrEditModel
类型编写自定义模型绑定器,以构建TopicCreateOrEditModel
的实例(如果当前控制器是TopicsController
)
或者,不知道您当前使用的继承,只需删除
NamedEntityController
中的Edit
(以及类似的CRUD方法),因为我看不到它的值。如果您有充分的理由支持它的存在,请忽略此建议。显然,MVC传递的是NamedEntityCreateOrEditModel
的实例,而不是TopicCreateOrEditModel
。在这种情况下,由于我看不到Edit
的多态性值,所以我想明确地将其标记为new
应该可以(是的,这是一个hack)
更传统的方法可能是为NamedEntityCreateOrEditModel
类型编写自定义模型绑定器,以构建TopicCreateOrEditModel
的实例(如果当前控制器是TopicsController
)
或者,不知道您当前使用的继承,只需删除
NamedEntityController
中的Edit
(以及类似的CRUD方法),因为我看不到它的值。如果您有充分的理由证明其存在,请忽略此建议。在操作中明确使用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();
}
}
公共类A{}
公共B类:A{}
公共类控制器{
[HttpPost]
公共虚拟操作结果编辑(){
A=新的A();
TryUpdateModel(a);
if(ModelState.IsValid)
a、 save();
}
}
公共类B控制器:A控制器{
[HttpPost]
公共覆盖操作结果编辑(){
B=新的B();
TryUpdateModel(b);
if(ModelState.IsValid)
b、 save();
}
}
这为我修复了模棱两可的MethodException,并正确路由了对
Edit
操作的调用。但是,可能存在我不知道的安全问题。在操作中明确使用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();
}
}
公共类A{}
公共B类:A{}
公共类控制器{
[HttpPost]
公共虚拟操作结果编辑(){
A=新的A();
TryUpdateModel(a);
if(ModelState.IsValid)
a、 save();
}
}
公共类B控制器:A控制器{
[HttpPost]
公共覆盖操作结果编辑(){
B=新的B();
TryUpdateModel(b);
if(ModelState.IsValid)
b、 save();
}
}
这为我修复了模棱两可的MethodException,并正确路由了对
Edit
操作的调用。但是,可能存在我不知道的安全问题。必须将其传递给前者,否则无法覆盖。我以前曾将基类强制转换为它们的子类,当我知道对象实际上是子类时,但在这种情况下,它只是没有发生。它必须传递给前者,否则它无法重写。我以前曾将基类强制转换为它们的子类,当我知道对象实际上是子类时,但在这种情况下,它只是没有发生。从技术上讲,如果参数发生变化(编译时警告),它不是新的。这是否真的会
[HttpPost]
public new ActionResult Edit(TopicCreateOrEditModel Model) { ... }
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();
}
}