การกำหนดเส้นทาง MVC URL เส้นทางไปยังเส้นทางที่ผิดเพราะเหตุใด

คำถาม:

นี่คือ RegisterRoutes ของฉัน:

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");


            routes.Add("ImagesRoute", new Route("graphics/{*filename}", new HttpRuntime.Routing.ImageRouteHandler()));


            // insert_dateti
            routes.MapRoute(
                "Default", // Routenname
                "{controller}/{action}/{id}", // URL mit Parametern
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameterstandardwerte
                //new { controller = "Home", action = "Splash", id = UrlParameter.Optional } // Parameterstandardwerte
                //new { controller = "Folders", action = "Content", id = UrlParameter.Optional } // Parameterstandardwerte
            );



        } // End Sub RegisterRoutes

และนี่คือผู้จัดการเส้นทางของฉัน

using System;
using System.IO;
using System.Web;
using System.Linq; 
using System.Web.UI;
using System.Web.Routing;
using System.Web.Compilation; 
using System.Collections.Generic; 


namespace HttpRuntime.Routing
{ 


    public class ImageRouteHandler : IRouteHandler 
    {


        public string MapRemoteLocation(string strPath)
        {
            if (string.IsNullOrEmpty(strPath))
                return "";

            string strBaseURL = "http://madskristensen.net/themes/standard/";
            return strBaseURL + strPath;
        }

        public IHttpHandler GetHttpHandler(RequestContext requestContext) 
        { 


            string filename = requestContext.RouteData.Values["filename"] as string; 

            if (string.IsNullOrEmpty(filename)) 
            {
                // return a 404 HttpHandler here
                requestContext.HttpContext.Response.StatusCode = 404;
                requestContext.HttpContext.Response.End();
                return null;
            } // End if (string.IsNullOrEmpty(filename)) 
            else 
            { 
                requestContext.HttpContext.Response.Clear();
                requestContext.HttpContext.Response.ContentType = GetContentType(filename);
                requestContext.HttpContext.Response.Redirect(MapRemoteLocation(filename));


                // find physical path to image here.   
                //string filepath = requestContext.HttpContext.Server.MapPath("~/test.jpg");


                // string stPath = requestContext.HttpContext.Request.Url.AbsolutePath;
                //requestContext.HttpContext.Response.WriteFile(filepath); 
                //requestContext.HttpContext.Response.End();
            } // End Else of if (string.IsNullOrEmpty(filename)) 

            return null; 
        } // End Function GetHttpHandler


        public static void MsgBox(object obj)
        {
            if (obj != null)
                System.Windows.Forms.MessageBox.Show(obj.ToString());
            else
                System.Windows.Forms.MessageBox.Show("obj is NULL");
        } // End Sub MsgBox


        private static string GetContentType(String path) 
        { 
            switch (Path.GetExtension(path)) 
            { 
                case ".bmp": return "Image/bmp"; 
                case ".gif": return "Image/gif"; 
                case ".jpg": return "Image/jpeg"; 
                case ".png": return "Image/png"; 
                default: break;
            } // End switch (Path.GetExtension(path))  
            return "";
        } // End Function GetContentType


    } // End Class ImageRouteHandler : IRouteHandler 


}  // End Namespace HttpRuntime.Routing

เป้าหมายของสิ่งนี้คือเมื่อฉันมีสิ่งนี้ใน /Home/Index.cshtml

<img src="graphics/mads2011.png?v=123" title="Compose E-Mail" alt="Compose E-Mail" />

จะดาวน์โหลดรูปภาพจากโฮสต์ระยะไกล

มันทำงานได้ดีตราบใดที่ฉันมี

routes.Add("ImagesRoute", new Route("graphics/{filename}", new HttpRuntime.Routing.ImageRouteHandler()));

แต่เมื่อฉันเปลี่ยนมันเป็น

routes.Add("ImagesRoute", new Route("graphics/{*filename}", new HttpRuntime.Routing.ImageRouteHandler()));

เพื่ออนุญาตโฟลเดอร์ย่อย จากนั้นระบบจะเปลี่ยนเส้นทางทุกการกระทำของ URL ไปที่ /graphics

เช่น. เมื่อฉันมี

$(function () {
        $("#divJsTreeDemo").jstree({ 
        "json_data" : {
            "ajax" : {
                 "url": "@Url.Action("GetNodesJson", "Home")"
                 //"url": "@Url.Action("GetTreeData", "Home")"
                ,"async" : true

ใน Home/Index.cshtml

URL สำหรับการเรียก AJAX บนหน้า HTML ที่เป็นผลลัพธ์จะกลายเป็น

"url": "/graphics?action=GetNodesJson&amp;controller=Home"

ทำไมเป็นเช่นนี้? และฉันจะแก้ไขสิ่งนี้ได้อย่างไร? ถ้าฉันย้าย ImagesRoute ของฉันไปที่ด้านล่าง JavaScript จะกำหนดเส้นทางอย่างถูกต้อง แต่จากนั้นฉันก็ไม่สามารถรับรูปภาพระยะไกลได้อีกต่อไป เนื่องจากมีการกำหนดเส้นทางไปยังตัวควบคุม "กราฟิก" ซึ่งไม่มีอยู่ --> ข้อยกเว้นไม่มีมุมมองดังกล่าว...


person Stefan Steiger    schedule 05.10.2011    source แหล่งที่มา
comment
ฉันชอบ aspnetmvc มาก... ฉันเกลียดการกำหนดเส้นทางอย่างยิ่ง ฉันรู้สึกถึงความเจ็บปวดของคุณ. ขออภัยฉันไม่สามารถช่วยได้   -  person Jamiec    schedule 05.10.2011
comment
โอ้ ความช่วยเหลือที่เป็นไปได้ประการหนึ่งคือฉันใช้ตัวดีบักเกอร์เส้นทางจาก mvccontrib.codeplex.com เมื่อมีเส้นทาง ปัญหา.   -  person Jamiec    schedule 05.10.2011


คำตอบ (1)


เมื่อสร้างลิงก์จากเส้นทาง การ ImagesRoute ของคุณโดยใช้ {*filename} จะเป็นไปตามเงื่อนไขทั้งหมด ดังนั้นเส้นทางนั้นจะถูกใช้เพื่อสร้างลิงก์เสมอหากอยู่ก่อนเส้นทาง Default ของคุณในตารางเส้นทางของคุณ อย่างไรก็ตาม เมื่อประมวลผลคำขอ ระบบจะทำงานตามที่คาดไว้ เนื่องจากเส้นทาง ImagesRoute จะตอบสนองได้เฉพาะคำขอที่เริ่มต้น http://mysite.com/graphics/... เท่านั้น

เพื่อแก้ไขปัญหานี้ คุณจะต้องย้าย ImagesRoutes ไว้ใต้เส้นทางเริ่มต้น จากนั้นคุณจะต้องเพิ่ม RouteConstraint ให้กับเส้นทางเริ่มต้น เพื่อให้คำขอใดๆ ที่ขึ้นต้นด้วย graphics จะล้มเหลวในเส้นทางเริ่มต้น

เปลี่ยนเส้นทางเริ่มต้นของคุณดังนี้:

routes.MapRoute(
    "Default", // Routenname
    "{controller}/{action}/{id}", // URL mit Parametern
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // defaults
    new { controller = @"^(?!graphics).+" } // constraint
);
person counsellorben    schedule 05.10.2011
comment
เยี่ยมมาก ได้ผล! ขอบคุณมาก ! แม้ว่าฉันต้องบอกว่าฉันยังไม่เข้าใจว่าทำไม @Url.Action(GetNodesJson, Home) ซึ่ง /Home/GetNodesJson พอใจ /graphics/whatever หรือยิ่งกว่านั้นว่าทำไม @Url.Action(ActionName, ControllerName) จึงกลายเป็นกราฟิก/ชื่อคอนโทรลเลอร์/ActionName ฉันเดาว่ามันแค่เติมเส้นทาง 2 ที่ขยายเข้าไปในเส้นทาง 1 ... ฉันคิดว่าฉันต้องอ่านแหล่งที่มาของ MVC เพื่อทำความเข้าใจส่วนเส้นทางนั้น - person Stefan Steiger; 06.10.2011
comment
เนื่องจากพารามิเตอร์ ImagesRoute URL ของคุณประกอบด้วยการจับคู่แบบโลภรายการเดียว จึงตรงกับลิงก์ใดๆ ก็ตามที่สร้างโดย MVC ในด้านการสร้างลิงค์ ทุกอย่างตรงกับเส้นทางนั้น โปรดทำเครื่องหมายว่าตอบแล้ว ขอบคุณ. - person counsellorben; 06.10.2011