【问题标题】:How to map 2 routes to the same URL?如何将 2 条路由映射到同一个 URL?
【发布时间】:2015-09-29 23:11:03
【问题描述】:

我希望网页根据之前访问的网页做不同的事情。

基本上,我知道如何制作具有持久持久性的数据。但是,我的方法涉及使用查询字符串,但我不希望第二个用户能够使用之前创建的查询字符串访问网页。因此,我试图通过将多个路由映射到单个 url 来解决这个问题。这在 C# MVC 中可行吗?

具体来说,每当我从我的视图中单击我的链接(它可以在下面找到)时,被调用的路由只是具有 URL Search_History_Page 的第一条路由。这意味着具有相应操作方法的路由不会被调用。 The_Search_History_Page

这是我的 route.config

using System.Web.Mvc;
using System.Web.Routing;

namespace CBCM_Audio_Searcher
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute(
                name: "Route_That_Leads_To_The_Home_Page_As_The_First_Page",
                url: "The_Home_Page",
                defaults: new { controller = "First_", action = "Goes_To_The_Home_Page_As_The_First_Page"}
            );

            routes.MapRoute(
                name: "Route_That_Leads_To_The_Search_History_Page_As_The_First_Page",

                url: "The_Search_History_Page",
              defaults: new { controller = "First_", action = "Goes_To_The_Search_History_Page_As_The_First_Page", id = 1}
            );

            routes.MapRoute(
               name: "Route_That_Leads_To_The_Search_History_Page_From_The_Home_Page",
               url: "The_Search_History_Page",
               defaults: new { controller = "First_", action = "Goes_To_The_Search_History_Page_From_The_Home_Page", id=0 }
           );
        }
    }
}

这是我的控制器。

using System.Web.Mvc;
using System.Diagnostics; 

namespace CBCM_Audio_Searcher.Controllers
{
    public class First_Controller : Controller
    {
        public ActionResult Goes_To_The_Home_Page_As_The_First_Page()
        {

            Database_Data_Modifier_And_Extractor  Database_Data_Modifier_And_Extractor=new  Database_Data_Modifier_And_Extractor();  

            if (Database_Data_Modifier_And_Extractor.Checks_If_A_User_Can_Access_The_Website() == false)
            {
                return Redirect("http://www.google.com");  
            }

            else 
            {
                ViewData["User_ID"]=Database_Data_Modifier_And_Extractor.User_ID;         
                return View("The_Home_Page");
            }
        }
        public ActionResult Goes_To_The_Search_History_Page_As_The_First_Page(string User_ID,string DummyVariable, int id)
        {
            Debug.WriteLine(id); 
            return View("The_Search_History_Page"); 
        }
        public ActionResult Goes_To_The_Search_History_Page_From_The_Home_Page(string User_ID, string DummyVariable, int id)
        {
            Debug.WriteLine(id);
            return View("The_Search_History_Page");
        }

    }
}

这是我的 The_Home_Page_View。

@Html.ActionLink("Your Search Results", "Goes_To_The_Search_History_Page_From_The_Home_Page", "First_", new { User_ID = ViewData["User_ID"], DummyVariable = "a"}, null)  

我的 The_Search_History_Page 视图为空。

【问题讨论】:

  • 动作选择器在这种情况下会很有帮助。
  • 我认为这对我没有帮助。我希望网址相同。动作选择器改变了 url。
  • 属性路由能解决您的问题吗?这个想法是您可以使用查询字符串参数作为路由条件。 blogs.msdn.com/b/webdev/archive/2013/10/17/…

标签: c# asp.net-mvc url model-view-controller routing


【解决方案1】:

MVC 具有为方法指定动作名称的功能。您可以通过使用ActionNameAttribute 装饰方法并传递新的动作名称作为参数来指定名称。

所以每当对/Home/Bar的请求到来时,它都会交给MyActionMethod方法进行处理。

public class HomeController : Controller
{
    [ActionName("Bar")]
    public ActionResult MyActionMethod()
    {
        return Content("Foo");
    }

    [MyActionSelector]
    [ActionName("Foo")]
    public ActionResult Foo()
    {
        return Content("Foo");
    }

    [MyActionSelector]
    [ActionName("Foo")]
    public ActionResult Foo2()
    {
        return Content("Foo2");
    }
}

当请求进入时,MVC 将根据路由表和ActionNameAttribute 查找将处理请求的方法。当 MVC 为请求找到两个以上的方法时,它会抛出 AmbiguousMatchException

从方法列表中,您可以通过创建自定义ActionMethodSelectorAttribute 来指定处理请求的方法。当ActionMethodSelectorAttribute 被修饰为任何方法时,MVC 将在执行方法返回响应之前执行IsValidForRequest。如果IsValidForRequest 返回true,MVC 将执行返回响应的方法。否则 MVC 将查找匹配路由条件的其他方法。

要创建自己的属性,您必须扩展 ActionMethodSelectorAttribute 类并覆盖 IsValidForRequest 方法。 IsValidForRequest 方法有 controllerContextmethodInfo 作为输入参数。根据有多少方法能够满足请求,可以多次调用此方法。 每次methodInfo 都会有关于应该处理请求的方法的不同信息(基于路由表/ActionNameAttribute)。

public class MyActionSelectorAttribute : ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
    {
        HttpRequestBase request = controllerContext.RequestContext.HttpContext.Request;
        // your custom method selection logic goes here
        // select method based on previously searched term
        if (request.QueryString["foo"] != null && methodInfo.Name == "Foo")
        {
            return true;
        }
        else if (request.QueryString["foo2"] != null && methodInfo.Name == "Foo2")
        {
            return true;
        }
        return false;
    }
}

在我们的例子中,当请求来自/Home/Foo时,MVC 有两个方法FooFoo2 应该处理请求。正如我之前所说,在执行任何返回响应的方法之前,MVC 将为这两种方法调用MyActionSelectorAttribute.IsValidForRequest。出于说明目的,我们正在抓取 QueryString 并检查

1) 如果查询字符串中存在 foo 且方法也是 Foo 则返回 true(表示允许执行 Foo 方法)

2) 否则,如果查询字符串包含 Foo2 并且方法也是 Foo2 则返回 true(表示允许执行 Foo2 方法)

3) 否则返回 false。

【讨论】:

  • 谁能帮我解释一下上面的代码?我认为这段代码可能对我没有多大帮助,因为我认为编写自定义方法选择逻辑是令人困惑的部分。
  • @AlexanderKao 我已经更新了答案并附上了解释。
  • 我实际上想出了一种方法,如何仅使用基本知识来完成我想要的事情。啊啊啊啊啊啊啊!无论如何,谢谢。
  • 我将总结一下我的方法,即如何在不混淆 url 的情况下使查询字符串 url 不可访问(99% 的时间)。
  • 一般的想法是使用查询字符串创建至少两个到 url 的路径。在您希望人们能够访问的路径中,创建一个中间方法,该方法重定向到您想要返回视图的操作。第二条路径将直接访问我之前提到的那个动作。在中间方法中,您告诉数据库将“以前是否访问过此页面”的值增加到 1。
猜你喜欢
  • 1970-01-01
  • 2016-08-08
  • 2019-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-26
  • 1970-01-01
  • 2019-03-29
相关资源
最近更新 更多