C# 定制路线不';不能使用默认的mvc路由

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

我正在学习MVC

到目前为止,我已经创建了3个模型

  • 课程
  • 招生
  • 学生
  • 我有两个控制器

  • 家庭控制器
  • 学生控制员
  • 我可以查看学生列表、有关学生的详细信息,包括他们在课程中的课程和成绩、编辑学生详细信息以及添加新学生

    在这一点上,我想了解更多关于路由的信息,因为我一直在使用默认的映射路由

    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,你帮了我很大的忙。谢谢你的明确指示。你给了我很大的洞察力。