Attribute routing not working with dictionaries

asp.net-web-api asp.net-web-api2 attributerouting dapper

Question

Being new to attribute routing, I'd like to ask for help getting this to work.

This test is a simple dynamic DB table viewer: Given a table name (or stored query name or whatever) and optionally some WHERE parameters, return query results.

Table COMPANIES (one of any number of tables which has an associated SELECT query stored somewhere, keyed by table name):

ID  NAME    HQ  INDUSTRY
1   Apple   USA Consumer electronics
2   Bose    USA Low-quality, expensive audio equipment
3   Nokia   FIN Mobile Phones

Controller:

[Route("view/{table}/{parameters}")]
public object Get(string table, Dictionary<string, string> parameters) {
    var sql = GetSql(table);
    var dbArgs = new DynamicParameters(parameters);
    return Database.Query(sql, dbArgs); // Return stuff/unrelated to problem
}

SQL stored in some resource or table. Obviously the parameters must match exactly:

SELECT * FROM companies
WHERE name = :name
-- OR hq = :hq
-- OR ...etc. Doesn't matter since it never gets this far.

Request (Should look clean, but the exact URL format isn't important):

www.website.com/view/companies?hq=fin --> 404: No matching controller www.website.com/view/companies/hq=fin --> parameters is null www.website.com/view/companies/hq=fin&name=nokia --> Exception: A potentially dangerous Request.Path value was detected from the client (&).

When I use: [Route("view/{table}{parameters}")] I get:

A path segment cannot contain two consecutive parameters. They must be separated by a '/' or by a literal string. Parameter name: routeTemplate. Makes sense.

My question is: How do I accept a table name and any number of unknown parameters in the usual key1=val1&key2=val2 form (not some awkward indexed format like the one mentioned here) which will be later bound to SQL parameters, preferably using a vanilla data structure rather than something like FormCollection.

Accepted Answer

I don't think that binding URL parameters to a Dictionary is built-in to the framework. I'm sure there's a way to extend it if you wanted to.

I think quickest (but still acceptable) option is to get the query string parameters using Request.GetQueryNameValuePairs() like this:

[Route("view/{table}")]
public object Get(string table) {
    Dictionary<string, string> parameters = Request.GetQueryNameValuePairs()
        .ToDictionary(x => x.Key, x => x.Value);
    var sql = GetSql(table);
    var dbArgs = new DynamicParameters(parameters);
    return Database.Query(sql, dbArgs); // Return stuff/unrelated to problem
}


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why