C# 定制路线不';不能使用默认的mvc路由
我正在学习MVC 到目前为止,我已经创建了3个模型C# 定制路线不';不能使用默认的mvc路由,c#,asp.net-mvc,asp.net-mvc-routing,C#,Asp.net Mvc,Asp.net Mvc Routing,我正在学习MVC 到目前为止,我已经创建了3个模型 课程 招生 学生 我有两个控制器 家庭控制器 学生控制员 我可以查看学生列表、有关学生的详细信息,包括他们在课程中的课程和成绩、编辑学生详细信息以及添加新学生 在这一点上,我想了解更多关于路由的信息,因为我一直在使用默认的映射路由 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
我有一个学生数据库,所有学生都有唯一的姓氏。我知道,通常不建议这样做,因为姓氏不是唯一的,但它适用于这个小型学习项目。因此,我想要实现的是能够键入/students/{action}/{lastname}
并查看有关该学生的详细信息。所以我在我的学生控制器中创建了一个新的动作方法
public ActionResult Grab(string studentName)
{
if (studentName == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var student = db.Students.FirstOrDefault(x => x.LastName.ToLower() == studentName.ToLower());
if (student == null)
return HttpNotFound();
return View(student);
}
我在RouteConfig.cs文件中添加了一个新路由
//Custom route
routes.MapRoute(
name: null,
url: "{controller}/{action}/{studentName}",
defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional }
);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace ContosoUniversity
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//Custom route
routes.MapRoute(
name: null,
url: "{controller}/{action}/{studentName}",
defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional }
);
}
}
}
最后,我创建了一个名为Grab的新视图,它显示了关于学生的详细信息
现在,当我输入/student/grab/Norman
时,它会给出姓Norman的学生的详细信息
这太棒了。但现在我有一个问题。当我尝试使用一些原始URL时,如/Student/Details/1
他们不再工作了。我得到一个400错误
我做的第一件事是将默认路线移动到我创建的自定义路线之上
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//Custom route
routes.MapRoute(
name: null,
url: "{controller}/{action}/{studentName}",
defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional }
);
这解决了这个问题,但在我以前工作的抓取路径上导致了400错误。如何在不出现400错误的情况下同时使用这两个选项
这是我的完整RouteConfig.cs文件
//Custom route
routes.MapRoute(
name: null,
url: "{controller}/{action}/{studentName}",
defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional }
);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace ContosoUniversity
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//Custom route
routes.MapRoute(
name: null,
url: "{controller}/{action}/{studentName}",
defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional }
);
}
}
}
这是我的整个StudentController.cs文件
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using ContosoUniversity.DAL;
using ContosoUniversity.Models;
namespace ContosoUniversity.Controllers
{
public class StudentController : Controller
{
private SchoolContext db = new SchoolContext();
// GET: Student
public ActionResult Index()
{
return View(db.Students.ToList());
}
// GET: Student/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
public ActionResult Grab(string studentName)
{
if (studentName == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var student = db.Students.FirstOrDefault(x => x.LastName.ToLower() == studentName.ToLower());
if (student == null)
return HttpNotFound();
return View(student);
}
// GET: Student/Create
public ActionResult Create()
{
return View();
}
// POST: Student/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "LastName, FirstMidName, EnrollmentDate")]Student student)
{
try
{
if (ModelState.IsValid)
{
db.Students.Add(student);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View(student);
}
// GET: Student/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// POST: Student/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost, ActionName("Edit")]
[ValidateAntiForgeryToken]
public ActionResult EditPost(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var studentToUpdate = db.Students.Find(id);
if (TryUpdateModel(studentToUpdate, "",
new string[] { "LastName", "FirstMidName", "EnrollmentDate" }))
{
try
{
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DataException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
return View(studentToUpdate);
}
// GET: Student/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// POST: Student/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Student student = db.Students.Find(id);
db.Students.Remove(student);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
我会提供任何其他需要的细节。同样,我希望能够输入
http://localhost:49706/Student/Details/1
或http://localhost:49706/Student/Grab/Alexander
并获得相同的详细信息,因为Alexander is的studentID为1 您希望将自定义路由与默认路由url区分开来
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Custom route
routes.MapRoute(
name: "Students",
url: "Student/{action}/{id}",
defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional }
);
//General default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
操作参数还应与管线模板参数匹配
// GET: Student/Details/5
public ActionResult Details(int? id) {
if (id == null) {
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var student = db.Students.Find(id);
if (student == null) {
return HttpNotFound();
}
return View(student);
}
public ActionResult Grab(string id) {
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var student = db.Students.FirstOrDefault(x => x.LastName.ToLower() == id.ToLower());
if (student == null)
return HttpNotFound();
return View(student);
}
这将允许以下内容正确匹配
Student/Details/1
Student/Grab/Alexander
如果姓Alexander的学生的studentId为1,则两条路线相同(从模式匹配的角度):
id
和studentName
只是占位符。除此之外,它们没有其他意义,因此您基本上有一条路线定义了两次:
{controller}/{action}/{someindicator}
最终发生的情况是,无论首先命中哪个路由,都将满足请求
因此,如果要使用相同的“模式”,则需要以某种方式区分路由。我建议直接在路线中指出行动:
routes.MapRoute(
name: "StudentDetails",
url: "{controller}/Details/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
//Custom route
routes.MapRoute(
name: "GrabStudent",
url: "{controller}/Grab/{studentName}",
defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional }
);
你的答案是正确的,但我先看了另一个。我认为你的内容很好。谢谢你的时间。快速提问。我的url结构现在需要是/Student/Details?id=1,而不是Student/Details/1,这会给我一个400错误。你知道这是为什么吗?@在互联网上,这不应该。更新操作以使用与模板
studentId
中相同的名称,或者在它们相同后决定使用的名称。注意答案中名称如何从id
更改为studentId
,以匹配路线模板。所有需要id的操作都应更改为匹配。或者你也可以恢复为所有的id
,一旦模板也更新了,我就完全复制了你的代码,解决了我的问题。我不知道我做错了什么。最后一个问题。我的学生控制器的索引视图显示的详细信息链接不正确。因此,它显示的不是指向/student/Details/1的链接,而是/student/Details?id=1,当我转到它时,它给我一个400。我不知道如何修复这个问题,因为我的操作链接在Internet上看起来就像这个@Html.ActionLink(“Details”,“Details”,new{id=item.id}),它也需要更新以匹配占位符@Html.ActionLink(“Details”,“Details”,new{studentId=item.id})
。听到什么。如果您当前的所有代码都使用id
我建议您使用所有参数id,而不必更新所有代码。只需更新操作和路由。我会把答案更新到Match,你帮了我很大的忙。谢谢你的明确指示。你给了我很大的洞察力。