I'm trying to build a (mostly) restful service, but I'm struggling with one part of the design. We expose various resources, which on the server side look like:
public class Thing1 : Resource {
public string ABC {get;set;}
public string DEF {get;set;}
}
Where Resource
is a base class:
public class Resource {
public List<Link> Links {get;set;}
}
Where Link
s, in turn, just bind rel
s and uri
s. In this way, each Resource
has links to other resources, etc, and the consumer can navigate through the various resources that the service offers.
Some (but not all) resources are editable, and so the consumer will retrieve the resource, make changes to it, and then PUT
those changes back to the service. Of course, at that point, the service will perform validation as required (and deal with any concurrency issues).
But, as always, it would be nice if the consuming application could perform some validation up-front before even attempting the PUT
request, to cut down on unnecessary round trips (in much the same way that we might use javascript validation even though the server has to repeat it).
So, I'd like to include some validation information in our responses, so that the consuming application knows that (for instance), ABC
cannot be longer than 6 characters. It should be noted that, at present, the consumer can use the same resource classes (they're in a separate assembly, together with appropriate MediaTypeFormatter
classes) - adding attributes (e.g. System.ComponentModel.DataAnnotations.RequiredAttribute
) feels wrong because then the consuming application ends up with the validation as it was at the time they took the shared assembly, rather than as it may be now in the service.
There's also some validation that is more policy based where the actual validation properties cannot be computed until runtime.
tl;dr;
What's a good design for including "helpful" validation information in REST responses, alongside the actual resource, so that consuming applications can build good user experiences?
Maybe something like,
> GET /api/Thing/1
< 200 OK
< Content-Type: application/vnd.acme.resource+xml
<resource>
<ABC>blah</ABC>
<DEF>blurg</DEF>
<links>
<links rel="help" href="/api/help/things"/>
<links rel="http://acme.com/rels/validationrules" href="/api/validationrules/things"/>
</links>
</resource>
> GET /api/validationrules/things
< 200 OK
< Content-Type: application/vnd.acme.validationrules+xml
<rules resourceType="thing">
<property name="ABC" MaxLength="6"/>
<property name="DEF" MaxLength="8"/>
</rules>
I do something similar in my own API. Unfortunatly there is no standard media type that I am aware of that attempts to address this particular need. I suspect trying to define this type of media type causes the "kitchen sink" effect where everyone has different requirements and they all get thrown in and the end result is something too complicated for everyone.
However, defining your own media type that addresses your particular needs may be a very manageable challenge.
The important thing about this solution, in my opinion, is that /api/validationrules/things
should change very rarely and therefore can be privately cached by the client. This means that the client pays a very minimal cost for retreiving this information as a distinct resource.
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