6
\$\begingroup\$

I need to pass an array of values in Url.Action.

Currently I'm doing:

var redirectUrl = Url.Action("search", new {   
        q = criteria.Q,
        advanced = criteria.Advanced,
        salaryfrom = criteria.SalaryFrom,
        salaryto = criteria.SalaryTo,
    });

if (criteria.JobTypes != null)
    redirectUrl += criteria.JobTypes.Aggregate(string.Empty, (a, x) => a += "&jobTypes=" + x);

To give me something like:

/search?q=developer&advanced=false&salaryfrom=20000&salaryto=80000&jobTypes=Full%20Time&jobTypes=Contract

Is there a nicer/cleaner approach?

\$\endgroup\$
3
\$\begingroup\$

I assume you "own" the controller? If so, I'd serialize and deserialize the list as a comma separated string on each side. It'd also be nice if criteria.JobTypes is an empty list instead of a possible null, then you don't need the ?? below.

var redirectUrl = Url.Action("search", new {
    // ...
    jobTypes = String.Join(criteria.JobTypes ?? new string[0], ",")
}

And do jobTypes.split(",") in the action.

URL would look a bit nicer too:

/search?q=developer&advanced=false&salaryfrom=20000&salaryto=80000&jobTypes=Full%20Time,Contract
\$\endgroup\$
2
\$\begingroup\$

To expand on Lars-Erik's answer, you can also use the other overload, the one that takes a dictionary.
This is also useful to construct e.g. an input that might or might not be disabled.

RouteValueDictionary args = new RouteValueDictionary {
    {"q", criteria.Q},
    {"advanced", criteria.Advanced},
    {"salaryfrom", criteria.SalaryFrom},
    {"salaryto", criteria.SalaryTo},
};
if(criteria.JobTypes != null) {
    // Either foreach the jobTypes or go Lars-Erik's way (nicer).
    args.Add("jobTypes", "foo");
}

Take care about special characters!
If you don't fully control the input, you might get a jobType "R&D" that will break your url: /search?q=...&jobTypes=R&D gets you jobTypes=R.

\$\endgroup\$
2
\$\begingroup\$

You can add the array elements individually to the RouteValueDictionary -- you just have to change the name to match the model binding name for round trip purposes.

The second argument to your action can be a RouteValueDictionary as ANeves said.

RouteValueDictionary rvd = new RouteValueDictionary { { "name", "value"}, ...};
int i = 0;
criteria.JobTypes.ForEach(v => rvd.Add(String.Format("jobTypes[{0}]", i++), (object) v));
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.