【问题标题】:MVC4 Custom Routing - Validating Personalized UrlsMVC4 自定义路由 - 验证个性化 URL
【发布时间】:2016-12-09 08:03:50
【问题描述】:

我正在开发一个需要一些自定义路由的 MVC4 网站。这是一个只有几页的简单网站。例如:

/index
/plan
/investing
... etc.. a few others

通过管理面板,网站管理员可以创建“品牌”网站,这些网站基本上反映了上述内容,但换掉了一些东西,如品牌公司名称、徽标等。创建后,URL 看起来像

/{personalizedurl}/index
/{personalizedurl}/plan
/{personalizedurl}/investing

...等...(与非品牌页面完全相同的页面。

我正在使用控制器方法上的操作过滤器属性验证个性化 URL,如果在数据库中找不到,则返回 404。

这是我的一个操作示例:

[ValidatePersonalizedUrl]
[ActionName("plan")]
public ActionResult Plan(string url)
{
    return View("Plan", GetSite(url));
}

到目前为止很容易,并且在以下路线上效果很好:

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

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

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

    routes.MapRoute(
        "Branded", // Route name
        "{url}/{action}", // URL with parameters
        new { controller = "Default", action = "Index" } // Parameter defaults
    );

/*
    routes.MapRoute(
        "BrandedHome", // Route name
         "{url}/", // URL with parameters
         new { controller = "Default", action = "Index" } // Parameter defaults
    );
*/
}

我目前遇到的问题是底部注释掉的路线。我希望能够转到 /{personalizedurl}/ 并让它找到正确的操作(默认控制器中的索引操作)。现在,在底线被注释掉的情况下,我得到一个 404,因为它认为它是一个动作并且它没有找到。当我取消注释时,索引页面可以正常工作,但是单个操作不会 /plan 例如,因为它认为它是一个 pUrl 并且无法在数据库中找到它。

无论如何,很抱歉这个问题太长了。任何有关如何设置的帮助或建议将不胜感激。

詹姆斯

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 asp.net-mvc-routing


    【解决方案1】:

    问题是 MVC 将使用第一个匹配的 url,因为第二个路由是:

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

    并且与您的 /{personalizedurl}/ 匹配,它将路由到 Default/{action}。

    你想要的有点棘手!我认为个性化是动态的,而不是一些静态的品牌公司列表,并且您不希望每次添加/删除新公司时都重新编译和部署。

    我认为你需要在控制器中处理这个问题,它在路由中无法正常工作;除非它是个性化公司的静态列表。您将需要能够检查第一部分是否是您的操作之一,并检查它是否是一家有效的公司,我将给您一个简单字符串数组的示例。我相信您将通过为您的个性化公司查询某种数据存储来构建数组。我还创建了一个名为 PersonalizedViewModel 的快速视图模型,它以字符串作为名称。

    您的路线将被简化:

    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
      routes.MapRoute(
        name: "Admin",
        url: "Admin/{action}/{id}",
        defaults: new { controller = "Admin", action = "Index", id = UrlParameter.Optional }
      );
    
      routes.MapRoute(
        name: "Default",
        url: "{url}/{action}",
        defaults: new { controller = "Default", action = "Index", url = UrlParameter.Optional }
      );
    }
    

    这是我的示例使用的视图模型:

    public class PersonalizedViewModel
    {
      public string Name { get; private set; }
      public PersonalizedViewModel(string name)
      {
        Name = name;
      }
    }
    

    以及默认控制器:

    public class DefaultController : Controller
    {
      private static readonly IEnumerable<string> personalizedSites = new[] { "companyA", "companyB" };
      private static readonly IEnumerable<string> actions = new[] { "index", "plan", "investing", "etc" };
    
      public ActionResult Index(string url)
      {
        string view;
        PersonalizedViewModel viewModel;
        if (string.IsNullOrWhiteSpace(url) || actions.Any(a => a.Equals(url, StringComparison.CurrentCultureIgnoreCase)))
        {
          view = url;
          viewModel = new PersonalizedViewModel("Default");
        }
        else if (personalizedSites.Any(s => s.Equals(url, StringComparison.CurrentCultureIgnoreCase)))
        {
          view = "index";
          viewModel = new PersonalizedViewModel(url);
        }
        else
        {
          return View("Error404");
        }
    
        return View(view, viewModel);
      }
    
      public ActionResult Plan(string url)
      {
        PersonalizedViewModel viewModel;
        if (string.IsNullOrWhiteSpace(url))
        {
          viewModel = new PersonalizedViewModel("Default");
        }
        else if (personalizedSites.Any(s => s.Equals(url, StringComparison.CurrentCultureIgnoreCase)))
        {
          viewModel = new PersonalizedViewModel(url);
        }
        else
        {
          return View("Error404");
        }
    
        return View(viewModel);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-03-13
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多