MVC路由配置异常:访问NewsImages默认Action报403错误
问题分析与解决:NewsImages控制器访问出现403.14错误
先梳理下你的配置和代码情况:
你的RouteConfig路由配置
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, namespaces: new[] { "GPTKish.Controllers" } );
NewsImages控制器的Index方法代码
public class NewsImagesController : Controller { private DatabaseContext db = new DatabaseContext(); // GET: NewsImages public ActionResult Index(int selectedNewsid) { List<NewsImage> newsImages = db.NewsImages.Include(n => n.News).Where(c => c.NewsId == selectedNewsid).ToList(); ViewBag.NewsTitle = newsImages[1].News.Title; return View(newsImages); } }
问题根源
访问http://localhost:23594/News正常,是因为News控制器的Index方法没有必填参数(或者有默认值),MVC能直接匹配默认路由里的action=Index规则,顺利调用方法。
但NewsImages的Index方法要求一个必填的int类型参数selectedNewsid,当你访问/NewsImages时,默认路由会尝试匹配controller=NewsImages, action=Index,但找不到不需要参数的Index方法。这时候IIS会误以为你要访问NewsImages这个物理目录,而目录没有启用目录浏览权限,就返回了403.14禁止访问的错误。
另外还有个隐藏坑:你代码里直接用newsImages[1],如果查询出来的newsImages数量小于2,会直接抛出索引越界异常,这个也要记得处理。
解决办法
方法1:让selectedNewsid参数变为可选
给参数设置默认值或者改成可空类型,这样即使不带参数也能调用Index方法:
// 方式A:设置参数默认值 public ActionResult Index(int selectedNewsid = 0) { List<NewsImage> newsImages = db.NewsImages.Include(n => n.News).Where(c => c.NewsId == selectedNewsid).ToList(); // 避免索引越界的判断 ViewBag.NewsTitle = newsImages.Count >= 2 ? newsImages[1].News.Title : "暂无相关图片"; return View(newsImages); } // 方式B:改成可空类型 public ActionResult Index(int? selectedNewsid) { if(!selectedNewsid.HasValue) { // 没有传参数时的处理逻辑,比如返回空列表或提示 ViewBag.NewsTitle = "请指定新闻ID"; return View(new List<NewsImage>()); } List<NewsImage> newsImages = db.NewsImages.Include(n => n.News).Where(c => c.NewsId == selectedNewsid.Value).ToList(); ViewBag.NewsTitle = newsImages.Count >= 2 ? newsImages[1].News.Title : "暂无相关图片"; return View(newsImages); }
方法2:新增专属路由,让参数成为路由一部分
如果selectedNewsid是必须传递的参数,你可以添加一个专门针对NewsImages的路由(要放在默认路由前面):
routes.MapRoute( name: "NewsImages", url: "NewsImages/{selectedNewsid}", defaults: new { controller = "NewsImages", action = "Index" }, namespaces: new[] { "GPTKish.Controllers" } ); // 原来的默认路由放在后面 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, namespaces: new[] { "GPTKish.Controllers" } );
之后访问http://localhost:23594/NewsImages/1(1是具体的新闻ID)就能正常匹配到Index方法了。
方法3:访问时明确携带参数
如果不想改代码和路由,访问时直接在URL里传递参数即可,比如:http://localhost:23594/NewsImages/Index?selectedNewsid=123
内容的提问来源于stack exchange,提问作者Seyed Morteza Mousavifar
相关产品推荐
相关产品推荐

