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

时间:2011-07-07 21:22:03

标签: .net asp.net-mvc asp.net-mvc-3

我正在开发一个ASP.Net MVC 3项目,其中很多非常简单的实体只需要来自Administrative界面的基本CRUD支持。所有这些实体都有一个带有Id,Name的简单域对象,并且为此目的有一个抽象基类NamedEntity

我有一个基本的控制器NamedEntityController<T> where T : NamedEntity可以处理简单的crud操作,其所有方法都是虚拟的。有一个很好的小NamedEntityCreateOrUpdateModel<T>用于传回数据&amp;发表意见。

现在我有一个名为NamedEntity的{​​{1}}的特定子类,它具有其他属性,特别是与其他主题具有父/子关系,因此我们需要捕获父对象的整数Id这对其他Topic操作毫无意义。为此,我将子类化为NamedEntityTopicsController: 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抱怨说,新方法和基类方法之间的操作不明确。

这个问题有一个简单的解决方案吗?在这种情况下,我可以完全绕过基类控制器/模型,并且基本上说'如果你需要除了简单的字段之外的其他字段,不要继承',但这似乎非常错误,特别是因为域对象继承。

3 个答案:

答案 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方法),因为我无法看到它的值。如果你有充分的理由存在它,请忽略这个建议。