MVC 3 - Косые черты и пробелы в маршруте - PullRequest
4 голосов
/ 13 декабря 2011

В моем 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-адрес, подобный следующему:

/ Блог / Категория / Проекты% 20 /% 20Lab

И когда я перехожу по ссылке, я получаю эту ошибку:

Описание: HTTP 404. Ресурс, который вы ищете (или один изего зависимости) можно было удалить, изменить его имя или временно недоступно.Пожалуйста, просмотрите следующий URL и убедитесь, что он написан правильно.

Запрошенный URL: / Блог / Категория / Проекты / Лаборатория

При отладке не выполняется действие index.

У меня вопрос, как мне это сделать?работать, или я должен выполнить некоторую проверку ввода при создании имен категорий, чтобы этого не происходило?

Ответы [ 2 ]

0 голосов
/ 14 декабря 2011

Прежде всего, спасибо Tyrsius, Romias и eth0 за их предложения.

Я решил, что не хочу использовать идентификатор для категории, и я не хотел создавать обработчик маршрута, поскольку это не решает проблему с корнем.

Вместо этого я создаю проверочный атрибут с именем "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;
        }
    }
}

Теперь, когда я иду, чтобы добавить категорию:

adding a category that I know will fail validation

Я получаю этот ответ автоматически:

Failed response with validation

JS еще не работает, но мой контроллер может определить состояние модели, и это ответ от него, поэтому атрибут работает правильно.

Это в основном проверяет косую черту с пробелами с любой / любой стороны. Обратите внимание, что это не полный валидатор URL, но он подойдет для моего текущего проекта. Если у кого-то есть какие-либо улучшения, пожалуйста, дайте мне знать, и я исправлю этот ответ.

Я не очень хорошо с RegExp, поэтому не наследовал от RegularExpressionAttribute, а также я не хотел предоставлять сообщение об ошибке внутри моей модели. Этот атрибут действительно должен быть построен, поскольку при использовании категорий в качестве частей URL появляется больше правил.

0 голосов
/ 13 декабря 2011

Как предположил Тирсиус, будет легче передавать идентификатор категории, но если вы хотите передать имя, тогда я бы предложил использовать Url.Encode() каждый раз, когда вы создаете ссылку или создаете пользовательский UrlHelper, чтобы сделать это для вас. , Как только он достигнет действия вашего контроллера, просто выполните Url.Decode(), чтобы вернуть исходную строку.

Более понятный способ - создать собственный обработчик маршрута (реализовать IRouteHandler), который сделает это за вас.

...