I'm using OData Attribute Routing for an OData endpoint. Here is an example of what I have:
[ODataRoutePrefix("Profile")]
public class ProfileODataController : ODataController
{
[ODataRoute]
[EnableQuery]
public IHttpActionResult Get()
{
var repo = new Repositories.ProfileRepository();
return Ok(repo.GetProfiles());
}
[ODataRoute("({key})")]
[EnableQuery]
public IHttpActionResult Get([FromODataUri] string key)
{
var repo = new Repositories.ProfileRepository();
var result = repo.GetProfiles().SingleOrDefault(x => x.Id== key);
if (result == null) return NotFound();
return Ok(result);
}
}
Here is my set up:
config.MapODataServiceRoute("odata", "odata", ModelGenerator.GetEdmModel());
Here is my EdmModel Generation:
public static IEdmModel GenerateEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Profile>("Profile").EntityType.HasKey(x => x.Id);
return builder.GetEdmModel();
}
The urls /odata/Profile
and /odata/Profile('someid')
both work, but when I try to access the $metadata endpoint (/odata/$metadata#Profile
), I get the following error:
{"Message":"No HTTP resource was found that matches the request URI 'http://****/odata/$metadata'.","MessageDetail":"No type was found that matches the controller named 'Metadata'."}
Do I need to create a controller/action for serving the metadata? If so, how is that action implemented?
Turns out it had to do with my replacement of the IAssembliesResolver
.
I had implemented a custom version to provide only the component assemblies that I had implemented controllers in. However, as the error said, it couldn't find a controller named MetadataController
. Turns out, OData implements one: System.Web.OData.MetadataController
, which provides for the $metadata
keyword.
Since I had implemented my own IAssembliesResolver
, the System.Web.OData
assembly wasn't being included, and $metadata
failed. Once I discovered this, and updated my assembly resolver to explicitly include the OData assembly, it now works as it should.