3

私は何か間違ったことをしていると確信していますが、運が悪かったのでこれに数時間を費やした後、誰かが私を助けてくれたら本当にうれしいです.

ルーティング システムは、最初のルーティング登録でのみパラメータを尊重するようです。

これは私のglobal.asax.csがどのように見えるかです

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication4
{


    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

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

            routes.MapRoute(
                     "t", // Route name
                     "{controller}/{action}/{i}/{v}",  
                     new { i = UrlParameter.Optional, v = UrlParameter.Optional }  
                 );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", 
                new {  id = UrlParameter.Optional } 
            );





        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

ホームコントローラーはこんな感じ

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication4.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index(int? id)
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About(int? a)
        {
            return View();
        }



    }
}

問題は、このURLを試すときです

http://localhost:52230/Home/Index/2

ID は常に null です。しかし、試してみると http://localhost:52230/Home/Index?id=2 ....うまくいきます。

他のルートの前にホーム/インデックスを登録しても機能します。その場合、後で登録されたルートには、パラメーターの受け入れにおいて同じ問題があります。

ここで何が間違っていますか?

アップデート:

これらの両方のコントローラーを機能させたいのですが、ルート登録はどのようになりますか?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication4.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index(int? id)
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }




    }
}

2台目のコントローラー

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication4.Controllers
{
    public class VisitorController : Controller
    {
        //
        // GET: /VisitorSecurityPoints/


        public ActionResult Test(string i,string v)
        {

            return View();
        }

    }
}
4

3 に答える 3

2

ルートは、特定のものから一般的なものへと並べられています。つまり、MVC は、要求された URL を確認するときに、常に最も具体的なルートに一致させようとします。ルートは、ルート リストの下の方にあるほど、より「貪欲」になります。

v問題の 2 つのルートを詳しく見てみると、パラメーターが指定されていない限り、MVC が 2 つを区別する方法がないことがわかります。どちらにもcontrolleractionパラメータがあり、オプションの 3 番目のパラメータもあります。が指定されていない場合v、MVC は、このような優先順位システムが導入されていない限り、使用するルートを知る方法がありません。そのため、ルーティング テーブル内のルートの順序が重要になります。

このように MVC が 2 つのルートを区別できるようにする方法はいくつかありますが、問題のパラメーターのデータ型によって異なります。たとえば、iDateTimeではなく である場合、日付のみに一致するルート制約intを追加できます。制約の詳細については、この記事を参照してください。

また、Richard の RouteDebugger の使用に関するアドバイスにも賛成です。これは、このような状況を理解するのに非常に役立ち、よりクリーンなルーティング テーブルの設計につながる可能性があります。

編集

最後にタグを付けたときに URL が「機能する」理由?id=2は、MVC がクエリ文字列内の一致するアクション パラメーターに直接モデル バインドしようとするためです。ただし、ルートに一致するパラメーターは、クエリ文字列で指定された値よりも優先されることに注意してください。たとえば、次のルートを使用します。

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

に移動http://localhost:50754/home/index/2するとid2になります。 に
移動すると4にhttp://localhost:50754/home/index/?id=4なります。 に 移動すると2 になります。 id
http://localhost:50754/home/index/2?id=4id

コメント後に更新

特定の問題を解決する最も簡単な方法は、ルート テーブルを変更して次のルートを含めることです。

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

    routes.MapRoute(
        "visitors", // Route name
        "visitor/{action}/{i}/{v}", // URL with parameters
        new
        {
            controller = "Visitor", action = "Test",
            i = UrlParameter.Optional, v = UrlParameter.Optional
        }
    );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

{action}パラメータがこの新しいルートにまだ存在していることに注意してください。これにより、コントローラー内の他のアクションに対応するために拡張することが少し簡単になります。コントローラーに存在するアクションへのルートを制約する必要がある場合は、前述のようにルート制約を追加する必要があります。

このアプローチの 1 つの注意点は、いくつかの URL に一致する新しいルートを常に指定している場合、ルート テーブルが非常に急速に大きくなる可能性があることです。これにより、既存のルーティングのために新しい機能をサイトに追加することがより困難になり、メンテナンスもより困難になる可能性があります. 可能な限り、デフォルト{controller}/{action}/{id}ルートと一致するようにルートを設計するようにしてください。長い目で見ればメンテナンスとデバッグが非常に簡単になるからです。

于 2012-08-05T21:25:32.900 に答える
1

あなたの他のルート(「t」)が最初に一致するためだと思います。

于 2012-08-05T20:55:12.910 に答える
0

RouteDebuggerを使用して、一致しているルートを確認できます。nuget を使用してインストールするだけです。

PM> install-package RouteDebugger

ページを表示すると、すべてのルートが一覧表示され、どのルートが一致したかが示されます。最初に一致したルートが使用されます。

于 2012-08-05T20:57:54.017 に答える