Saturday 15 January 2011

c# - OData v4 - Select specific field in an Entity -



c# - OData v4 - Select specific field in an Entity -

i using odata v4 web api 2.2.

i have entity called "person" composite keys of "firstname" , "lastname". looks this:

public class person { public string firstname {get; set;} public string lastname {get; set;} public double age {get; set;} }

in order back upwards composite keys, have added uri conventions on top of default one, looks this:

public class compositekeyroutingconvention : entityroutingconvention { public override string selectaction(odatapath odatapath, httpcontrollercontext controllercontext, ilookup<string, httpactiondescriptor> actionmap) { var action = base.selectaction(odatapath, controllercontext, actionmap); if (action != null) { var routevalues = controllercontext.routedata.values; if (routevalues.containskey(odatarouteconstants.key)) { var keyraw = (string)routevalues[odatarouteconstants.key]; var compoundkeypairs = keyraw.split(','); if (!compoundkeypairs.any()) { homecoming action; } foreach (var compoundkeypair in compoundkeypairs) { var pair = compoundkeypair.split('='); if (pair.length != 2) { continue; } var keyname = pair[0].trim(); var keyvalue = pair[1].trim(); routevalues.add(keyname, keyvalue); } } } homecoming action; }

my calling code trying access age of person so:

http://localhost:46028/person(firstname='blah',lastname='blu')/age

i error:

{ "error":{ "code":"","message":"no http resource found matches request uri 'http://:46028/person(firstname='blah',lastname='blu')/age'.","innererror":{ "message":"no routing convention found select action odata path template '~/entityset/key/property'.","type":"","stacktrace":"" } } }

my controller has 2 methods:

public iqueryable<person> get() { homecoming _db.people; } public person get([fromodatauri] string firstname, [fromodatauri] string lastname) { var person = _db.people .firstordefault(x => x.firstname == firstname && x.lastname== lastname); if (person == null) { throw new httpresponseexception(request.createresponse(httpstatuscode.notfound)); } homecoming person; }

turns out there simple solution. web api not back upwards composite keys well, have propertyroutingconvention i'm looking except doesn't work composite keys.

fixed creating "compositekeypropertyroutingconvention" given below:

public class compositekeypropertyroutingconvention : propertyroutingconvention { public override string selectaction(odatapath odatapath, httpcontrollercontext controllercontext, ilookup<string, httpactiondescriptor> actionmap) { var action = base.selectaction(odatapath, controllercontext, actionmap); homecoming new compositekeyroutingbehaviour().selectaction(action, odatapath, controllercontext, actionmap); } } public class compositekeyroutingbehaviour { public string selectaction(string action, odatapath odatapath, httpcontrollercontext controllercontext, ilookup<string, httpactiondescriptor> actionmap) { if (action != null) { var routevalues = odatapath.segments.firstordefault(x => x.segmentkind == odatarouteconstants.key); if (routevalues != null) { var keyraw = routevalues.tostring(); var formatter = new keyvalueformatter(); var keypairs = formatter.formatrawkey(keyraw); if (!keypairs.any()) { homecoming action; } foreach (var pair in keypairs) { controllercontext.routedata.values.add(pair.key, pair.value); } } } homecoming action; } } public class keyvalueformatter { public idictionary<string, string> formatrawkey(string rawkey) { var formattedkeys = new dictionary<string, string>(); if (string.isnullorwhitespace(rawkey)) homecoming formattedkeys; var keybuilder = new stringbuilder(); var valuebuilder = new stringbuilder(); var keybuilding = true; var keys = new list<string>(); var values = new list<string>(); (var = 0; < rawkey.length; i++) { var currentchar = rawkey[i]; var nextchar = < rawkey.length - 1 ? rawkey[i + 1] : (char?)null; var prevchar = > 0 ? rawkey[i - 1] : (char?)null; if (currentchar == '=' && keybuilding) { keybuilding = false; keys.add(keybuilder.tostring()); keybuilder.clear(); continue; } if (!keybuilding && currentchar == ',' && prevchar.hasvalue && prevchar.value == '\'') { keybuilding = true; values.add(valuebuilder.tostring()); valuebuilder.clear(); continue; } if (keybuilding) { keybuilder.append(currentchar); } else { valuebuilder.append(currentchar); } if (!keybuilding && !nextchar.hasvalue) { values.add(valuebuilder.tostring()); valuebuilder.clear(); } } if (keys.count != values.count) { throw new invaliddataexception("the key not formatted valid pairs. key was: " + rawkey); } (var = 0; < keys.count; i++) { formattedkeys.add(keys[i].trim(), values[i].trim()); } homecoming formattedkeys; } }

the lastly class mumbo jumbo handle "," within info of keys themselves, haven't tested "'" within info yet, recommend that.

c# odata asp.net-web-api2

No comments:

Post a Comment