Question

Have a few custom content-types registered via

ContentTypeFilters.Register(contentType, StreamSerializer, StreamDeserializer);

and would like to restrict the display for routes on the metadata page. These content-types are only meant to be used with request dto's which are restricted to InternalNetworkAccess. Just looking to not clutter up the public facing metadata page with stuff that isn't necessary.

For the builtin contentTypes you would just add it under the RestrictAttribute. Is there a similar feature hidden somewhere else that isn't documented yet maybe for the custom types?

It looks like perhaps I could customize the MetadataFeature plugin and possibly restrict which request dto's get the content type and which don't. But I only just recently noticed that, and not sure how well that would turn out (also don't really know yet how to remove the MetadataFeature and safely replace with my own).

Essentially I only want this custom contentType visible on the metadata page for the requestDtos restricted to InternalNetworkAccess. Any ideas?

Edit:
Also am still on ServiceStack v3, but still interested in possibilities for v4.

Was it helpful?

Solution 2

So I found that the initial class handling the metadata requests was ServiceStack.MetadataFeature an IPlugin. This actually controls both the layout of the underlying example request/response page (for each content-type) as well as the overall "/metadata" page.

From this small segment

private IHttpHandler GetHandlerForPathParts(String[] pathParts)
{
    var pathController = string.Intern(pathParts[0].ToLower());
    if (pathParts.Length == 1)
    {
        if (pathController == "metadata")
            return new IndexMetadataHandler();

        return null;
    }
    ...
}

is where the handler for the actual "/metadata" page is sent off. You don't find the actual construction of the ContentTypes per request until you get down a little further, inside IndexMetadataHandler's parent class BaseSoapMetadataHandler in the method

protected override void RenderOperations(HtmlTextWriter writer, IHttpRequest httpReq, ServiceMetadata metadata)

An internal control is created (IndexOperationsControl) which has a method RenderRow, which is where all the magic occurs. Here you'll see some obvious checks for the "Operation" (which is another word for the Dto now) and ContentType like

if (this.MetadataConfig.IsVisible(this.HttpRequest, EndpointAttributesExtensions.ToFormat(config.Format), operation))

So all that needs to be done is create your own class of IndexOperationsControl and handle the config.Format in the RenderRow method. The config.Format is simply everything after the forward slash in the ContentType you registered, so if it was "application/x-my-type" the config.Format String will be "x-my-type". Operation is simply the class name of the RequestDto. Unfortunately because the class is marked internal it means you pretty much have to copy it completely instead of using inheritance. In order to keep a 1:1 likeness with how the pages are generated by default you'll also need a copy of the internal classes ListTemplate, TableTemplate, and XsdTypes (used in construction of IndexOperationsControl).

After this you simply need your own IndexMetadataHandler and overload RenderOperations (you can use inheritance for this one) to create your new IndexOperationsControl. Also we'll need our own MetadataFeature equivalent IPlugin but we'll need to copy it completely and modify GetHandlerForPathParts to return our new IndexMetadataHandler. The only other thing to do is remove MetadataFeature and add our own as a plugin.

    // removing default metadata feature
    Plugins.RemoveAll(x => x is MetadataFeature);
    // add our custom one
    Plugins.Add(new CustomMetadataFeature());

Voila, you can display custom ContentTypes exactly how you want per RequestDto.

OTHER TIPS

You can prevent your custom type from showing up in the metadata using.

If your content type is application/yourformat you would use:

SetConfig(new HostConfig {
    IgnoreFormatsInMetadata = new HashSet<string>{ "yourformat" }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top