ASP.NET MVC QueryString по умолчанию значения переопределения поставляется?

голоса
25

Использование ASP.NET MVC Preview 5 (хотя это также было опробовано с Beta), оказывается, что QueryString по умолчанию в маршруте переопределить значение, которое передается в по строке запроса. Репрография, чтобы написать контроллер, как это:

public class TestController : Controller
{
    public ActionResult Foo(int x)
    {
        Trace.WriteLine(x);
        Trace.WriteLine(this.HttpContext.Request.QueryString[x]);
        return new EmptyResult();
    }
}

С маршрутом отображаются следующим образом:

routes.MapRoute(
    test,
    Test/Foo,
    new { controller = Test, action = Foo, x = 1 });

А затем вызвать его с этой относительной URI:

/Test/Foo?x=5

Трассировочная я вижу:

1
5

Итак, другими словами значение по умолчанию, который был создан для маршрута всегда передается в метод, независимо от того, был ли он на самом деле поставляется на строку запроса. Обратите внимание, что если по умолчанию для строки запроса удаляется, т.е. маршрут отображается следующим образом:

routes.MapRoute(
    test,
    Test/Foo,
    new { controller = Test, action = Foo });

Затем контроллер ведет себя, как ожидалось, и значение передается в качестве значения параметра, давая выходные данные трассировки:

5
5

Это смотрит на меня как ошибка, но мне было бы очень удивительно, что ошибка, как это все еще может быть в бета-версии в рамках ASP.NET MVC, поскольку querystrings с дефолтов не совсем эзотерическое или края случае функция , так что это почти наверняка моя вина. Любые идеи, что я делаю не так?

Задан 19/01/2009 в 17:49
источник пользователем
На других языках...                            


4 ответов

голоса
30

Лучший способ посмотреть на ASP.NET MVC с QueryStrings, чтобы думать о них как ценности, что маршрут не знает о. Как выяснилось, QueryString не является частью RouteData, поэтому, вы должны сохранить то, что вы передаете в качестве строки запроса отдельно от значений маршрута.

Способ работать вокруг них, чтобы создать значения по умолчанию себя в действии, если значения, передаваемые из QueryString равны нулю.

В вашем примере, маршрут знает х, поэтому ваш URL должен действительно выглядеть следующим образом:

/Test/Foo or /Test/Foo/5

и маршрут должен выглядеть следующим образом:

routes.MapRoute("test", "Test/Foo/{x}", new {controller = "Test", action = "Foo", x = 1});

Чтобы получить поведение, которое вы искали.

Если вы хотите, чтобы передать значение строки запроса, скажем, как номер страницы, то вы могли бы сделать это:

/Test/Foo/5?page=1

И ваши действия должны измениться, как это:

public ActionResult Foo(int x, int? page)
{
    Trace.WriteLine(x);
    Trace.WriteLine(page.HasValue ? page.Value : 1);
    return new EmptyResult();
}

Теперь тест:

Url:  /Test/Foo
Trace:
1
1

Url:  /Test/Foo/5
Trace:
5
1

Url:  /Test/Foo/5?page=2
Trace:
5
2

Url:  /Test/Foo?page=2
Trace:
1
2

Надеюсь, что это помогает прояснить некоторые вещи.

Ответил 19/01/2009 в 19:36
источник пользователем

голоса
15

Один из моих коллег нашел ссылку , которая указывает , что это дизайн и, кажется , автор этой статьи поднял вопрос с командой MVC , говоря это был переход от более ранних выпусков. Ответ от них был ниже (на «странице» вы можете прочитать «х» , чтобы он относится к вопросу выше):

Это дизайн. Маршрутизация не занимается со значениями строк запроса; это касается себя только со значениями из RouteData. Вы должны вместо этого удалить запись «страница» из словаря по умолчанию, а в любом метод действия сам по себе или в фильтре установить значение по умолчанию для «страницы», если он еще не установлен.

Мы надеемся, что в будущем более простой способ, чтобы отметить параметр, как явно приходя из RouteData, строки запроса или формы. Пока это не реализовано выше решение должно работать. Пожалуйста, дайте нам знать, если это не так!

Таким образом , представляется , что такое поведение является «правильным», но это так ортогональна принципу наименьшего удивления , что я до сих пор не могу в это поверить.


Не Изменить # 1: Обратите внимание , что после детализирует метод , как значения по умолчанию, однако это больше не работает в качестве ActionMethodсобственности , которую он использует для доступа к MethodInfoбыл удален в последней версии ASP.NET MVC. Я в настоящее время работает над альтернативой и разместим его , когда сделано.


Изменить # 2: Я обновил эту идею в связанной почте для работы с выходом Preview 5 ASP.NET MVC, и я считаю, он должен также работать с выпуском бета-версии, хотя я не могу гарантировать, что это, как мы не продвинулись в этой версии пока нет. Это так просто, что я только что отправил его рядный здесь.

Во- первых , есть атрибут по умолчанию (мы не можем использовать существующий .NET DefaultValueAttributeкак он должен наследовать CustomModelBinderAttribute):

[AttributeUsage(AttributeTargets.Parameter)]
public sealed class DefaultAttribute : CustomModelBinderAttribute
{
    private readonly object value;

    public DefaultAttribute(object value)
    {
        this.value = value;
    }

    public DefaultAttribute(string value, Type conversionType)
    {
        this.value = Convert.ChangeType(value, conversionType);
    }

    public override IModelBinder GetBinder()
    {
        return new DefaultValueModelBinder(this.value);
    }
}

Обычай Связующее:

public sealed class DefaultValueModelBinder : IModelBinder
{
    private readonly object value;

    public DefaultValueModelBinder(object value)
    {
        this.value = value;
    }

    public ModelBinderResult BindModel(ModelBindingContext bindingContext)
    {
        var request = bindingContext.HttpContext.Request;
        var queryValue = request .QueryString[bindingContext.ModelName];
        return string.IsNullOrEmpty(queryValue) 
            ? new ModelBinderResult(this.value) 
            : new DefaultModelBinder().BindModel(bindingContext);
    }
}

И тогда вы можете просто применить его к параметрам методы, которые приходят в на строки запроса, например,

public ActionResult Foo([Default(1)] int x)
{
    // implementation
}

Работает как шарм!

Ответил 19/01/2009 в 18:34
источник пользователем

голоса
0

Я думаю, что параметры причины QueryString не переопределяют значения по умолчанию, чтобы остановить человек, хакерских URL-адрес.

Кто-то может использовать URL-адрес которого включен контроллер QueryString, действие или другие значения по умолчанию вы не хотите их изменить.

Я имел дело с этой проблемой, делая то, что @ Дейл-Ragan предложил и борьбы с ней в методе действий. Работает на меня.

Ответил 01/10/2009 в 11:06
источник пользователем

голоса
-3

Я думал, что точка с маршрутизацией в MVC, чтобы избавиться от querystrings. Как это:

routes.MapRoute(
    "test",
    "Test/Foo/{x}",
    new { controller = "Test", action = "Foo", x = 1 });
Ответил 19/01/2009 в 18:27
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more