2017-04-21 1 views
1

Je suis le Microsoft Contoso University Tutorial pour apprendre MVC.L'itinéraire personnalisé ne fonctionne pas avec l'itinéraire mvc par défaut

Jusqu'à présent, j'ai créé 3 modèles

  1. Cours
  2. inscription
  3. étudiant

Et j'ai 2 contrôleurs

  1. HomeController
  2. StudentController

Je peux afficher une liste d'étudiants, des détails sur les étudiants, y compris les cours et les notes qu'ils ont dans les cours, modifier les détails de l'étudiant, et ajouter de nouveaux étudiants.

À ce stade, je voulais en savoir plus sur le routage depuis que j'avais utilisé par défaut Carte Route

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
); 

J'ai une base de données des étudiants qui ont tous les noms de famille uniques. Je suis conscient que cela n'est normalement pas recommandé car les noms de famille ne sont pas uniques, mais cela fonctionne pour ce petit projet d'apprentissage. Donc, ce que je voulais atteindre était de pouvoir taper /students/{action}/{lastname} et voir les détails sur l'étudiant. J'ai donc créé une nouvelle méthode d'action dans mon contrôleur d'étudiant.

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

Et j'ai ajouté une nouvelle route dans mon RouteConfig.cs fichier

//Custom route 
routes.MapRoute(
    name: null, 
    url: "{controller}/{action}/{studentName}", 
    defaults: new { controller = "Student", action = "Grab", id = UrlParameter.Optional } 
); 

Et enfin, je créé une nouvelle vue appelée Grab qui montre des détails sur l'étudiant.

Maintenant, quand je tape /student/grab/Norman il me donne les détails de l'étudiant avec le nom Norman

Laura Norman

C'est grand. Mais maintenant j'ai un problème. Lorsque j'essaie d'utiliser certaines de mes URL d'origine comme /Student/Details/1 , elles ne fonctionnent plus. Je reçois une erreur 400.

La première chose que je ne faisais que passer ma route par défaut au-dessus de la route personnalisée que j'ai fait

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

Et cela résout ce problème, mais provoque une erreur 400 sur mon itinéraire grab travail auparavant. Comment puis-je utiliser les deux en même temps sans avoir une erreur 400?

Voici fichier mes RouteConfig.cs plein

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


     } 
    } 
} 

Voici fichier mon StudentController.cs ensemble

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

Je vais vous donner d'autres détails nécessaires.Encore une fois, je veux être en mesure de taper http://localhost:49706/Student/Details/1 ou http://localhost:49706/Student/Grab/Alexander et obtenir les mêmes détails exacts puisque Alexander est a la idEtudiant 1.

Répondre

1

Vous voulez différencier votre itinéraire personnalisé à partir de l'url route par défaut

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

paramètres d'action doivent également correspondre au modèle d'itinéraire paramètres

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

Cela maintenant que les éléments suivants être correctement correspondance

Student/Details/1 
Student/Grab/Alexander 

étudiant fourni avec le dernier nom Alexander a le StudentID de 1

+0

Question rapide. Ma structure url doit maintenant être/Student/Details? Id = 1 plutôt que Student/Details/1 ce qui me donne une erreur de 400. Savez-vous pourquoi c'est? – onTheInternet

+1

@onTheInternet, Cela ne devrait pas être. mettre à jour les actions pour utiliser le même nom que dans le modèle 'studentId' ou ce que vous décidez d'utiliser une fois qu'elles sont identiques. Notez comment le nom a été changé de 'id' à' studentId' dans la réponse pour correspondre au modèle de route. Toutes les actions nécessitant l'identifiant doivent être modifiées pour correspondre. Ou vous pourriez revenir à les refaire tous, une fois le modèle mis à jour ainsi – Nkosi

+0

J'ai copié votre code exactement et cela a corrigé mon problème. Je ne sais pas ce que j'avais tort. Une dernière question. ma vue d'index pour mon contrôleur d'étudiant montre un lien incorrect pour des détails. Donc plutôt que le lien va/student/Details/1 il montre/Student/Details? Id = 1 qui me donne un 400 quand je vais à lui. Je ne suis pas sûr comment résoudre ce problème parce que mon lien d'action ressemble à ceci @ Html.ActionLink ("Détails", "Détails", nouveau {id = item.ID}) – onTheInternet

1

Les deux itinéraires sont les mêmes (du point de vue de correspondance de motif):

{controller}/{action}/{id} 

{controller}/{action}/{studentName} 

id et studentName ne sont que des espaces réservés. Ils détiennent pas de sens autre que celui, vous avez donc essentiellement un seul itinéraire défini deux fois:

{controller}/{action}/{someindicator} 

Ce qui finit par se produire est que quelle que soit la route est d'abord frappé servira la demande. Pour cette raison, si vous voulez utiliser le même "pattern", vous devez différencier les routes d'une manière ou d'une autre. Je suggère d'indiquer l'action directement dans la route:

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

Votre réponse était correcte mais j'ai lu l'autre en premier. Je vous ai upvoted pour avoir un bon contenu. Merci pour votre temps. – onTheInternet