I have the following problem: one of the system I'm working in most important features is a search page. In this page I have some options, like records per page, starting date, ending date, and the problematic one: type. One must have the possibility to choose more than one type (most of the time, all of them will be selected). To make that work, i created the following:
<div>
<label>Eventos:</label>
<div>
@Html.ListBox("events", Model.Events, new { style = "width: 100%" })
</div>
</div>
It creates a listbox where I can choose more than one option, and when the form is submited, my query string will look like this:
/5?period=9&events=1&events=3&recordsPerPage=10
There it is possible to see that two events (which is the type I was talking before) are created. The action method to this page takes a List<long>
as one of its arguments, which represents that two events
values. The problem begins when I want to use that with MVC Contrib. Their pager works just fine, but as I was requested, I created another pager, which displays links to five pages after and before the one the user is at. To do this, in a part of my code I have to do the following (which is very similar to the MVC Contrib pager, that works):
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;
}
And then:
@Html.ActionLink(page.ToString(), action, controller, GetRoute(page), null)
The problem is that it is a Dictionary, which makes the second time I set the value for routeValues["events"]
erase the previous.
Do you guys have any idea on how to work with it?
You can very well use helpers such as TextBoxFor() and LabelFor() if you so wish. There are two submit buttons - one with name attribute set to save and the other with name of cancel.
Yes, it's possible. Just make sure your views have same view model. From a technical stand point, views don't have to have the same view model implemented within the same action. There's just as long as the controller passes in the expected type.
Very good question. Unfortunately it is not easy to generate an url which has multiple query string parameters with the same name using the Html.ActionLink
helper. So I can see two possible solutions:
Write a custom model binder for long[]
that is capable of parsing a comma separated values. This way you can keep your GetRoute
method which will generate the following 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);
}
}
which you will register in Application_Start
:
ModelBinders.Binders.Add(typeof(long[]), new CommaSeparatedLongArrayModelBinder());
and then the following controller action will be able to understand the previous URL:
public ActionResult Foo(long[] events, int page, int period, int recordsPerPage)
{
...
}
Manually generate this anchor:
<a href="@string.Format("{0}?{1}&page=5", Url.Action("action", "controller"), Request.QueryString)">abc</a>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With