将参数绑定到复杂类型

时间:2018-12-11 06:59:56

标签: asp.net-mvc asp.net-mvc-5 asp.net-mvc-routing model-binding

我有一个带有多个链接的导航栏,如下所示:

<a href="MyController/Browse/2">MenuItem1</a>

此请求将触发我的操作方法:

public ActionResult Browse(int departmentId)
{
    var complexVM = MyCache.GetComplexVM(departmentId);
    return View(complexVM);
}

这是我的ComplexVM

public class ComplexVM 
{
    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }
}

MyCache是部门的静态列表,我将其保留在内存中,因此,当用户传入DepartmentId时,无需从数据库中获取相应的DepartmentName

这工作正常...但是如果我能以某种方式在自定义模型绑定程序中初始化ComplexVM,而不是在Controller中初始化它,那将是很好的选择。因此,我仍然想使用链接(菜单项目),但这一次,CustomModelBinder将我的参数2绑定到ComplexVM:它需要从MyCache查找id = 2的部门名称并初始化{{1 }},然后将ComplexVM传递给该操作方法:

ComplexVM

我想在不执行回发的情况下点击上面的控制器,因为我的导航栏中有很多菜单项链接...不确定是否可行?还是这是个好主意?

我看过this link,它描述了我想要的东西...但是我不确定路由如何工作...即路由public ActionResult Browse(ComplexVM complexVM) { return View(complexVM); } => id:2 < / p>


或者可以在ComplexVM中这样做,如下所示:

RouteConfig

2 个答案:

答案 0 :(得分:3)

那是可能的。这也是一个好主意:)将部分责任分担给模型/动作过滤器是很棒的。唯一的问题是,因为它们使用一些特殊的类来继承,所以测试它们有时可能比仅测试控制器要难一些。一旦掌握了它,那就更好了。

您的复杂模型应该看起来像

// Your model class
[ModelBinder(typeof(ComplexVMModelBinder)]
public class ComplexVMModel
{
   [Required]
   public int DepartmentId { get; set; }

   public string DepartmentName { get; set; }
}

// Your binder class
public class ComplexVMModelBinder : IModelBinder
{
     // Returns false if you can't bind.
     public bool BindModel(HttpActionContext actionContext, ModelBindingContext modelContext)
     {
         if (modelContext.ModelType != typeof(ComplexVMModel))
         {
             return false;
         }

         // Somehow get the depid from the request - this might not work.
         int depId = HttpContext.Current.Request.Params["DepID"];
         // Create and assign the model.
         bindingContext.Model = new ComplexVMModel() { DepartmentName = CacheLookup(), DepId = depId };

         return true;
     }
}

然后在操作方法的开头,检查ModelState以查看其是否有效。

有几件事会使模型状态无效(例如没有[Required]参数。)

public ActionResult Browse(ComplexVM complexVM)
{
    if (!ModelState.IsValid)
    {
        //If not valid - return some error view.
    }
}

现在,您只需要注册此Model Binder。

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    ModelBinders.Binders.Add(typeof(ComplexVMModel), new ComplexVMModelBinder());
}

您应该能够使用您提供的路由配置。

答案 1 :(得分:3)

我只需一点改动和一个技巧就可以实现这一目标

<a href="MyController/Browse?id=1">MenuItem1</a>

控制器动作

public ActionResult Browse(ComplexVM complexVM)
{
return View(complexVM);
}

查看模型

public class ComplexVM
{
    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }
    public ComplexVM()
    {
        this.DepartmentId = System.Convert.ToInt32(HttpContext.Current.Request("id").ToString);
        this.DepartmentName = "Your name from cache"; // Get name from your cache 
    }
}

这不使用模型联编程序。技巧可能会有所帮助。