Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding validation information to REST responses

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 Links, in turn, just bind rels and uris. 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?

like image 874
Damien_The_Unbeliever Avatar asked Mar 14 '13 08:03

Damien_The_Unbeliever


1 Answers

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.

like image 105
Darrel Miller Avatar answered Sep 20 '22 22:09

Darrel Miller