.net 具有子类模型的子类控制器

.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

我正在从事一个ASP.NETMVC3项目,其中许多非常简单的实体只需要从管理界面获得基本的CRUD支持。所有这些实体都有一个Id为Name的简单域对象,并且有一个抽象基类
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();
    }
}