ASP.NET MVC:如何将URL中的ID从控制器传递到视图?求替代方案
嘿,我来给你几个更靠谱的实现思路,解决你现在获取URL中项目ID并配合ViewModel的问题:
方法1:把ID直接整合进ViewModel(最推荐,符合MVC设计)
与其在视图里硬去读取路由数据,不如直接把需要的ID放到ViewModel里,让控制器和视图的交互更清晰:
首先修改你的Multipledata模型,新增一个ProjectId属性:
public class Multipledata { public int ProjectId { get; set; } public IEnumerable<Projects> projectss { get; set; } public IEnumerable<ProjectNotes> projectnotess { get; set; } }
然后在控制器里,把URL传来的ID赋值给ViewModel的这个属性:
public ActionResult ViewProject(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } BextecODBEntities DB = new BextecODBEntities(); var mymodel = new Multipledata(); mymodel.ProjectId = id.Value; // 把URL中的ID存入ViewModel mymodel.projectss = DB.Projects.ToList(); mymodel.projectnotess = DB.ProjectNotes.ToList(); return View("ViewProject", mymodel); }
最后在视图里,直接使用ViewModel里的ProjectId做判断,不用再依赖路由数据:
@foreach(var item in Model.projectss) { if(item.ID == Model.ProjectId) { @Html.DisplayText($"You have clicked on Project ID: {item.ID}") } }
这种方式的好处是,视图只需要依赖ViewModel的约定,不用关心ID是从哪里来的,代码更易维护,也符合MVC分离关注点的原则。
方法2:只加载当前ID对应的项目数据(性能更优)
如果你的视图只需要展示当前点击的项目信息,完全没必要把所有Projects数据都查出来,这样能减少数据库压力,视图代码也更简洁:
先给Multipledata新增一个CurrentProject属性:
public class Multipledata { public Projects CurrentProject { get; set; } public IEnumerable<ProjectNotes> projectnotess { get; set; } }
然后修改控制器,只查询目标项目和对应笔记:
public ActionResult ViewProject(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } BextecODBEntities DB = new BextecODBEntities(); // 只查询当前ID的项目 var targetProject = DB.Projects.FirstOrDefault(p => p.ID == id); if(targetProject == null) { return HttpNotFound(); // 项目不存在时返回404,更友好 } var mymodel = new Multipledata(); mymodel.CurrentProject = targetProject; // 还可以只查询该项目对应的笔记,减少数据量 mymodel.projectnotess = DB.ProjectNotes.Where(pn => pn.ProjectID == id).ToList(); return View("ViewProject", mymodel); }
视图里就不用循环判断了,直接展示:
@Html.DisplayText($"You have clicked on Project ID: {Model.CurrentProject.ID}") <!-- 还能直接展示项目的其他属性,比如名称、描述等 --> <p>Project Name: @Model.CurrentProject.Name</p>
这个方法不仅代码更简洁,还能提升页面加载速度,推荐在实际项目中使用。
方法3:用ViewBag临时传递ID(应急备选,不推荐长期用)
如果不想修改ViewModel,也可以用ViewBag临时传递ID,但这种方式是动态类型,编译时没有类型检查,容易出错,只适合快速测试:
控制器里添加:
public ActionResult ViewProject(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } BextecODBEntities DB = new BextecODBEntities(); var mymodel = new Multipledata(); mymodel.projectss = DB.Projects.ToList(); mymodel.projectnotess = DB.ProjectNotes.ToList(); // 把ID存入ViewBag ViewBag.ProjectId = id.Value; return View("ViewProject", mymodel); }
视图里使用:
@foreach(var item in Model.projectss) { if(item.ID == (int)ViewBag.ProjectId) { @Html.DisplayText($"You have clicked on Project ID: {item.ID}") } }
最后要确认的一点
记得检查你的路由配置,确保路由规则里包含id参数,比如默认路由:
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
如果路由没配置id,控制器就无法正确获取URL中的ID,这也是常见的坑点。
内容的提问来源于stack exchange,提问作者Zack Antony Bucci
相关产品推荐
相关产品推荐

