【问题标题】:MVC 3 - Slashes and spaces in routeMVC 3 - 路线中的斜线和空格
【发布时间】:2012-01-18 21:45:48
【问题描述】:

我在 Global.asax(MVC 3 网络项目)中定义了以下路由:

routes.MapRoute(
                "BlogCategory", // Route name
                "Blog/Category/{*category}", // URL with parameters
                new { controller = "Blog", action = "Index", category = "" } // Parameter defaults
            );

我的操作接受一个类别参数,如下所示:

   public ViewResult Index(string category, int page = 1)
        {
            PostListViewModel viewModel;
            if (string.IsNullOrEmpty(category))
            { 
....show all cats else show only the one passed in

这工作正常,并将类别传递给控制器​​,适当地过滤我的结果。

我的问题是当我创建的类别之一的类别名称看起来像这样时:

项目/实验室

(注意空格和斜线)

这会创建一个类似这样的 URL:

/Blog/Category/Projects%20/%20Lab

当我点击链接时,我收到了这个错误:

描述:HTTP 404。您正在寻找的资源(或其之一 依赖项)可能已被删除,名称已更改,或者是 暂时不可用。请查看以下 URL 并制作 确保拼写正确。

请求的 URL:/Blog/Category/Projects/Lab

调试时永远不会到达索引动作。

我的问题是,我怎样才能做到这一点,或者我必须在创建类别名称时进行一些输入验证以防止这种情况发生?

【问题讨论】:

  • 您是否考虑过传递类别 ID?
  • 您肯定需要对输入的值进行修整。而不仅仅是检查空格...某些字符不会显示在 URL 中(“Ñ”或其他非英文字符)...请记住那里还有其他语言。所以,为了避免这一切......我建议你选择类别 ID。

标签: asp.net-mvc-3 model-view-controller routes space slash


【解决方案1】:

正如 Tyrsius 建议的那样,传递类别 ID 会更容易,但如果你想传递名称,那么我建议每次创建链接时使用 Url.Encode() 或创建自定义 UrlHelper 来为你做.一旦它击中您的控制器操作,只需执行 Url.Decode() 即可取回原始字符串。

更简洁的方法是创建您自己的路由处理程序(实现 IRouteHandler)来为您完成。

【讨论】:

  • @Tyrsius 只是想知道,就像此页面上的堆栈溢出一样 - URL 的名称部分似乎自动被替换/编码:mvc-3-slashes-and-spaces-in-route 怎么来这不会发生在我的身上 - 即:Projects-/-Lab 或类似的东西?
【解决方案2】:

首先,感谢 Tyrsius、Romias 和 eth0 的建议。

我决定不想将 Id 用于类别,也不想创建路由处理程序,因为这并不能真正解决根本问题。

相反,我创建了一个名为 "UsedAsUrl" 的验证属性,并将其应用于我的域模型中的 Category.Name。 从开发人员的角度来看,这具有内置验证(对最终用户有利)和良好的可重用性的好处。

所以我的类别模型现在看起来像这样(注意 [UsedAsUrl] 属性):

public class Category
{
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        [UsedAsUrl]
        [MaxLength(50, ErrorMessage = "One word or groups of words please")]
        public string Name { get; set; }

        public virtual List<Post> Posts { get; set; }
}

而我创建的属性是这样的:

using System;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace CommonWebsiteUtilities.Attributes
{
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class UsedAsUrlAttribute : ValidationAttribute
    {
        public UsedAsUrlAttribute() : base("Must not contain a slash with spaces either side") {}

        public override bool IsValid(object value)
        {
            var input = value.ToString();
            var result = true;

            if (input.Contains("/"))
            {
                input = Regex.Replace(input, @"\s+", " ");
                if (input.Contains(" /")) result = false;
                if (input.Contains("/ ")) result = false;
                if (input.Contains(" / ")) result = false;
            }

            return result;
        }
    }
}

现在当我去添加一个类别时:

我会自动收到此回复:

JS 还没有工作,但我的控制器可以获取模型状态,这是它的响应,所以属性正常工作。

这基本上会检查斜线的任一侧/任何一侧是否有空格。请注意,这不是一个详尽的 URL 验证器,但它适用于我当前的项目。如果有人有任何改进,请告诉我,我会修改这个答案。

我不擅长使用 RegExp,所以不是从 RegularExpressionAttribute 派生的,而且我不想从我的模型内部提供错误消息。当使用类别作为 URL 部分时,随着更多规则的出现,这个属性真的应该被建立。

【讨论】:

  • 使用验证属性不能解决这个问题。
猜你喜欢
  • 2012-03-07
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 1970-01-01
  • 2020-01-25
  • 1970-01-01
  • 2021-02-02
  • 2019-03-08
相关资源
最近更新 更多