具有派生类的控制器操作

Gab*_*pez 3 c# polymorphism asp.net-mvc 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;}
}
Run Code Online (Sandbox Code Playgroud)

在我的控制器 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

设置控制器操作以便我可以传递派生类(StudentModel 或 TeacherModel)的正确方法是什么?

仅供参考,我尝试过自定义活页夹(见下文),但是,我不知道这是否是处理此问题的好方法。

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;
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*sch 5

多态模型绑定的最大问题之一是安全性。毕竟,您实际上允许客户端控制数据的解释方式。您必须小心,例如,用户无法修改帖子并告诉服务器您的 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);
}
Run Code Online (Sandbox Code Playgroud)

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

事实上,在这种情况下,假设您的模型类型基于某种安全机制,更好的解决方案是根据用户的角色实例化正确的模型。因此,当您的请求传入时,您会检查用户权限,如果他们是教师角色,则实例化一个 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);
}
Run Code Online (Sandbox Code Playgroud)