Как работать с более чем одним значением на ключ в ASP.NET MVC 3? - PullRequest
13 голосов
/ 18 мая 2011

У меня следующая проблема: одна из систем, над которой я работаю, - это страница поиска.На этой странице у меня есть несколько вариантов, таких как записи на странице, дата начала, дата окончания и проблемный: тип.Нужно иметь возможность выбрать более одного типа (в большинстве случаев все они будут выбраны).Чтобы это работало, я создал следующее:

<div>
    <label>Eventos:</label>
    <div>
        @Html.ListBox("events", Model.Events, new { style = "width: 100%" })
    </div>
</div>

Он создает список, в котором я могу выбрать более одного варианта, и когда форма отправляется, моя строка запроса будет выглядеть так:

/ 5? Period = 9 & events = 1 & events = 3 & recordsPerPage = 10

Там можно увидеть, что два события (это тот тип, о котором я говорил ранее) созданы.Метод действия для этой страницы принимает List<long> в качестве одного из аргументов, который представляет эти два значения events.Проблема начинается, когда я хочу использовать это с MVC Contrib.Их пейджер работает просто отлично, но, как мне было предложено, я создал еще один пейджер, который отображает ссылки на пять страниц после и до той, на которой находится пользователь.Для этого в части моего кода я должен сделать следующее (что очень похоже на пейджер MVC Contrib, который работает):

public RouteValueDictionary GetRoute(int page)
{
    var routeValues = new RouteValueDictionary();
    foreach (var key in Context.Request.QueryString.AllKeys.Where(key => key != null))
    {
        routeValues[key] = Context.Request.QueryString[key];
    }

    routeValues["page"] = page;
    return routeValues;
}   

И затем:

@Html.ActionLink(page.ToString(), action, controller, GetRoute(page), null)

Проблема в том, что это словарь, который заставляет во второй раз, когда я устанавливаю значение для routeValues["events"], стереть предыдущий.

Ребята, вы не знаете, как с ним работать?

Ответы [ 3 ]

4 голосов
/ 18 мая 2011

Очень хороший вопрос. К сожалению, с помощью хелпера Html.ActionLink нелегко сгенерировать URL с несколькими параметрами строки запроса с одинаковым именем. Таким образом, я вижу два возможных решения:

  1. Напишите пользовательский механизм связывания для long[], который способен анализировать значения через запятую. Таким образом, вы можете сохранить свой метод GetRoute, который будет генерировать следующий URL: period=9&events=1%2C3&recordsPerPage=10&page=5.

    public class CommaSeparatedLongArrayModelBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var values = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (values != null && !string.IsNullOrEmpty(values.AttemptedValue))
            {
                // TODO: A minimum of error handling would be nice here
                return values.AttemptedValue.Split(',').Select(x => long.Parse(x)).ToArray();
            }
            return base.BindModel(controllerContext, bindingContext);
        }
    }
    

    который вы зарегистрируете в Application_Start:

    ModelBinders.Binders.Add(typeof(long[]), new CommaSeparatedLongArrayModelBinder());
    

    и тогда следующее действие контроллера сможет понять предыдущий URL:

    public ActionResult Foo(long[] events, int page, int period, int recordsPerPage)
    {
        ...
    }
    
  2. Вручную сгенерировать этот якорь:

    <a href="@string.Format("{0}?{1}&page=5", Url.Action("action", "controller"), Request.QueryString)">abc</a>
    
0 голосов
/ 18 мая 2011

Вы должны написать либо методы расширения, предназначенные для коллекции routeValue, либо пользовательскую привязку модели, которая всегда преобразует ваш параметр Event в список. Если вы просматриваете Событие всегда как список, то список с обычной длиной 1 облегчит большинство проблем, с которыми вы сталкиваетесь.

На данный момент вы просто будете взаимодействовать с интерфейсом списка. Затем вы можете написать пользовательское связующее, чтобы позволить вам правильно разместить его в маршруте, или вы можете распаковать список обратно в строку запроса. Существует основанный на этом программный проект Unbinder для распаковки объектов в пары свойство / значение, которые можно легко использовать в строках запроса или в других целях.

0 голосов
/ 18 мая 2011

Попробуйте взглянуть на WinTellect PowerCollections , позволяет создать MultiDictionary, но при этом не может иметь дублирующихся ключей, но вы можете иметь несколько значений на ключ.

...