2017-04-21 136 views
1

我正在關注Microsoft Contoso University Tutorial以瞭解MVC。自定義路由不能使用默認mvc路由

到目前爲止,我已經創造了3種型號

  1. 招生
  2. 學生

而且我有2個控制器

  1. 的HomeController
  2. StudentController

,我可以查看學生名單,對學生的包括哪些課程,他們在課程,學生編輯的詳細信息,並添加新的學生成績有什麼細節。

在這一點上,我想更多地瞭解路由,因爲我一直在使用默認的地圖路線

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

最後,我創建了一個名爲抓住新的視圖,顯示關於學生的詳細信息。

現在,當我在​​鍵入它給我的學生的細節與姓諾曼

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鍵入並獲得相同的具體細節,因爲亞歷山大是有studentID的1

回答

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 

與姓氏亞歷山大提供的學生有1

+0

快速的問題。我的網址結構現在需要是/ Student/Details?id = 1而不是Student/Details/1,它給了我一個400錯誤。你知道這是爲什麼嗎? – onTheInternet

+1

@onTheInternet,這不應該。更新操作以使用與模板'studentId'相同的名稱,或者一旦它們相同就決定使用什麼。請注意,在匹配路由模板的答案中,名稱是如何從「id」更改爲「studentId」的。所有需要該id的操作都應該更改爲匹配。或者你可以恢復所有的'id',一旦模板被更新以及 – Nkosi

+0

我完全複製了你的代碼,並且解決了我的問題。我不知道我錯了什麼。最後一個問題。我的學生管理員的索引視圖顯示的鏈接不正確。所以,而不是鏈接去/學生/詳細/ 1它顯示/學生/詳細信息?id = 1,當我去它給我一個400。我不確定如何解決此問題,因爲我的操作鏈接看起來像這樣@ Html.ActionLink(「詳細信息」,「詳細信息」,新{id = item.ID}) – onTheInternet

1

的studentId兩條路線是相同的(從模式匹配的角度來看):

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

你的回答是正確的,但我先讀了另一個。我贊成你有好的內容。感謝您的時間。 – onTheInternet