自定义路由不适用于默认的mvc route

时间:2017-04-21 14:20:50

标签: c# asp.net-mvc asp.net-mvc-routing

我正在关注Microsoft Contoso University Tutorial学习MVC。

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

  1. 注册
  2. 学生
  3. 我有2个控制器

    1. 的HomeController
    2. StudentController
    3. 我可以查看学生列表,有关学生的详细信息,包括课程中的内容和成绩,编辑学生详细信息以及添加新学生。

      此时,我想了解更多有关路由的信息,因为我使用的是默认的Map Route

      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 }
      );
      

      最后我创建了一个名为Grab的新视图,其中显示了有关该学生的详细信息。

      现在当我输入/student/grab/Norman时,它会向我提供姓氏为Norman的学生的详细信息

      Laura Norman

      这很棒。但现在我有一个问题。当我尝试使用我的一些原始网址时/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文件

      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/1http://localhost:49706/Student/Grab/Alexander并获得相同的详细信息,因为Alexander的学生ID为1。

2 个答案:

答案 0 :(得分:1)

您希望区分自定义路由与默认路由网址

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的学生提供1岁的studentId

答案 1 :(得分:1)

两条路线都是相同的(从模式匹配的角度来看):

{controller}/{action}/{id}

{controller}/{action}/{studentName}

idstudentName只是占位符。除此之外,它们没有任何意义,因此您基本上只定义了两条路线:

{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 }
            );