Подтвердить что ты не робот

Как иметь дело с более чем одним значением за ключ в ASP.NET MVC 3?

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

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

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

?

/5 период = 9 & события = 1 & события = 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"] для удаления предыдущего.

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

4b9b3361

Ответ 1

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

  • Напишите настраиваемое связующее устройство для 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)
    {
        ...
    }
    
  • Вручную создайте этот якорь:

    <a href="@string.Format("{0}?{1}&page=5", Url.Action("action", "controller"), Request.QueryString)">abc</a>
    

Ответ 2

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

Ответ 3

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

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