4

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

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:

/博客/类别/项目%20/%20Lab

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

说明:HTTP 404。您要查找的资源(或其依赖项之一)可能已被删除、名称已更改或暂时不可用。请查看以下 URL 并确保其拼写正确。

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

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

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

4

2 回答 2

0

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

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

于 2011-12-13T13:02:27.773 回答
-1

首先,感谢 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 部分时,应该建立在更多规则的基础上。

于 2011-12-13T22:51:00.503 回答