c# - 具有派生类的 Controller 操作

标签 c# asp.net-mvc polymorphism derived-class

我有一个基类和两个派生类:

public class UserModel {
    public int Id {get; set; }
    public string Name {get; set; }
    public UserType UserType {get; set;}
}

public class StudentModel : UserModel {
    public string StudentProperty {get; set;}
}

public class TeacherModel : UserModel {
    public string TeacherProperty {get; set;}
}

在我的 Controller ProfileController.cs 中,我有以下两个操作:

public virtual ActionResult Detail(int id)
{
    var userModel = _userService.Get(id);

    return view(usermodel);
}

public virtual ActionResult Save(UserModel userModel)
{
    _userService.Save(userModel);
}

我有一个 View 来显示学生和老师的个人资料。我的问题如下:

保存时,使用 Action Save(UserModel userMode),StudentModel 和 TeacherModel 的附加属性(分别为 StudentProperty 和 TeacherProperty)显然没有绑定(bind)到 UserModel。所以我的问题是:

什么是设置 Controller Action 的正确方法,以便我可以传递派生类,StudentModel 或 TeacherModel?

仅供引用,我已经尝试过自定义 Binder (见下文),但是,我不知道这是否是处理此问题的好方法。

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    var form = controllerContext.HttpContext.Request.Form;

    switch (form["UserType"])
    {
        case "student":
            {
                var studentModel = bindingContext.Model as StudentModel;                        
                return studentModel;
            }
        case "Teacher":
            {
                var teacherModel = bindingContext.Model as TeacherModel;
                medico.TeacherProperty = form["TeacherProperty"];
                return teacherModel;
            }
    }

    return bindingContext.Model;
}

最佳答案

多态模型绑定(bind)的最大问题之一是安全性。毕竟,您实际上是在允许客户控制数据的解释方式。您必须小心,例如,用户不能修改帖子并告诉服务器您的 UserModel 实际上是 AdministratorModel 而您现在是管理员。

在你的用例中,我不知道你的应用程序是做什么的..但假设它是某种记录保存应用程序,想象一下学生可以通过改变提交给服务器的类型让自己成为一名老师,现在他们可以更改自己或其他学生的成绩。

但是,如果这不是真正的问题,那么一个相当简单的机制就是简单地执行此操作:

public virtual ActionResult Save(UserModel userModel)
{
    TeacherModel tmodel = null;
    StudentModel smodel = null;
    if (userModel.UserType == UserType.Teacher) {
        tmodel = new TeacherModel();
        UpdateModel<TeacherModel>(tmodel);
    }
    else {
        smodel = new StudentModel();
        UpdateModel<StudentModel>(smodel);
    }

    _userService.Save((UserModel)tmodel ?? smodel);
}

您在问题中提出的自定义模型联编程序方法也很好,如果在多种方法中使用它是更好的选择,但对于维护应用程序的人来说并不是那么明显。

事实上,在这种情况下,假设您的模型类型基于某种安全机制,更好的解决方案是根据用户的角色实例化正确的模型。所以,当你的请求进来时,你检查用户权限,如果他们是教师角色,你实例化一个 TeacherModel 对象,如果他们是学生,你实例化一个 StudentModel 对象,这样就没有最终用户可以改变它的工作方式。

也就是说,像这样:

public virtual ActionResult Save(UserModel userModel)
{
    TeacherModel tmodel = null;
    StudentModel smodel = null;
    // lookup user in database and verify the type of user they are
    var user = UserManager.GetUser(userModel.UserId)
    if (user.Role == "Teacher")
        tmodel = new TeacherModel();
        UpdateModel<TeacherModel>(tmodel);
    }
    else {
        smodel = new StudentModel();
        UpdateModel<StudentModel>(smodel);
    }

    _userService.Save((UserModel)tmodel ?? smodel);
}

关于c# - 具有派生类的 Controller 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27894272/

相关文章:

c# - 返回 HelperResult 和 MvcHtmlString 的 Lambda 表达式

C# 4.0 : Why MethodBag when there's ExpandoObject?

c# - WinForm无法滚动到底部

c# - LINQ to SQL - 如何高效地对多个条件执行 AND 或 OR 搜索

haskell - 为什么将未定义函数与未装箱类型一起使用时是多态的?

haskell - Haskell 中类型参数的正确类型签名

c# - 远程调试不会因错误而中断

jquery - 在某些 .cs 文件中调用 Dropdownlistfor onchange 事件的方法

asp.net-mvc - IValidateObject 如何清除/重置 ModelState.IsValid

objective-c - 如何避免不同的类别扩展定义相同的方法