Take the community feedback survey now.
Take the community feedback survey now.
I can see some magic has been applied at https://sdk.episerver.com/ContentDeliveryAPI/ by https://github.com/twskj/pretty-swag, my bad, had to dig further how to get swagger back
Have you tried Swashbuckle https://github.com/domaindrivendev/Swashbuckle?
Yep, this was the first thing, I installed this but getting 404 for /swagger and /swagger/docs/v1
K Khan, have you got this to work?
I just tried it out with version 2 of the Content Api and it works perfectly
Thanks for chasing, Yep, I managed that, but there was a lot of (EPiFind) fuss that I had to manage to get a correct swagger.
/K
Yes, a lot to filter away...
private class EPiServerDocumentFilter : IDocumentFilter
{
private readonly string[] assembliesToExclude = new string[]
{
"EPiServer",
"EPiServer.ApplicationModules",
"EPiServer.BaseLibrary",
"EPiServer.Configuration",
"EPiServer.Data.Cache",
"EPiServer.Data",
"EPiServer.Enterprise",
"EPiServer.Events",
"EPiServer.Find.Cms",
"EPiServer.Find",
"EPiServer.Find.Framework",
"EPiServer.Find.Optimizations",
"EPiServer.Find.Statistics",
"EPiServer.Find.UI",
"EPiServer.Find",
"EPiServer.Framework",
"EPiServer.ImageLibrary",
"EPiServer.Implementation",
"EPiServer.Licensing",
"EPiServer.LinkAnalyzer",
"EPiServer.Logging.Log4Net",
"EPiServer.Shell",
"EPiServer.Web.WebControls",
"EPiServer.WorkflowFoundation",
"EPiServer.XForms"
};
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
foreach (var description in apiExplorer.ApiDescriptions)
{
if (description.ActionDescriptor == null)
{
continue;
}
if (description.ActionDescriptor.ControllerDescriptor == null)
{
continue;
}
if (description.ActionDescriptor.ControllerDescriptor.ControllerType == null)
{
continue;
}
if (description.RelativePath.StartsWith("episerver"))
{
var apiPath = description.RelativePathSansQueryString();
swaggerDoc.paths.Remove("/" + apiPath);
continue;
}
var assemblyName = description.ActionDescriptor.ControllerDescriptor.ControllerType.Assembly.GetName();
if (this.assembliesToExclude.Contains(assemblyName.Name, StringComparer.InvariantCultureIgnoreCase))
{
var apiPath = description.RelativePathSansQueryString();
swaggerDoc.paths.Remove("/" + apiPath);
}
}
}
}
true, still, final swagger didn't work with Azure api management, dont remember exactly what was message, I have to rely on this swagger by changing end points that we got on yammer
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Episerver Content Api"
},
"basePath": "/",
"tags": [
{
"name": "Content Api",
"description": "Load IContent via IContentLoader"
},
{
"name": "Content Search Api",
"description": "Search for IContent via Episerver Find"
},
{
"name": "Site Definition Api",
"description": "Access site information, languages, and content roots"
}
],
"schemes": [
"https"
],
"paths": {
"/api/episerver/search/content": {
"get": {
"tags": [
"Content Search Api"
],
"summary": "Search for content",
"description": "",
"operationId": "contentSearch",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "filter",
"type": "string",
"in": "query",
"description": "Specify a filter string to be applied to the search. Filter strings utilize OData v4 filter syntax"
},
{
"name": "orderby",
"type": "string",
"in": "query",
"description": "Specify an orderby string to be applied to the search. Orderby strings utilize OData v4 sort syntax"
},
{
"name": "query",
"type": "string",
"in": "query",
"description": "Free text search to filter content. Supports query string syntax for searching in individual fields"
},
{
"name": "skip",
"type": "integer",
"in": "query",
"description": "Specify number of items to skip in returned search results (used for pagination)"
},
{
"name": "top",
"type": "integer",
"in": "query",
"description": "Specify number of items to return in search results (used for pagination)"
},
{
"name": "personalize",
"type": "boolean",
"in": "query",
"description": "Determines if returned content will be personalized (via the Visitor Group system) when returned. By default, content will be fetched in the context of an anonymous user."
},
{
"name": "expand",
"type": "string",
"in": "query",
"description": "Comma-separated list of reference properties (Content References, Content Areas) which should have their content fetched in the response. Passing \"*\" will load content in all reference properties in the return."
},
{
"name": "Accept-Language",
"type": "string",
"in": "header",
"description": "Determines in which languages content should be retrieved. Example - en-US,sv"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/SearchResponse"
}
}
}
}
}
},
"/api/episerver/content": {
"get": {
"tags": [
"Content Api"
],
"summary": "Retrieve multiple content items",
"description": "",
"operationId": "getContents",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "references",
"type": "array",
"items": {
"type": "string"
},
"in": "query",
"description": "List of content reference to load content"
},
{
"name": "guids",
"type": "array",
"items": {
"type": "string"
},
"in": "query",
"description": "List of content guids to use to load content"
},
{
"name": "expand",
"type": "string",
"in": "query",
"description": "Comma-separated list of reference properties (Content References, Content Areas) which should have their content fetched in the response. Passing \"*\" will load content in all reference properties in the returned response."
},
{
"name": "Accept-Language",
"type": "string",
"in": "header",
"description": "Determines in which language the content should be retrieved. Example - en-US"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/ExpandedContentApiModel"
}
}
}
}
}
},
"/api/episerver/content/{referenceORguid}": {
"get": {
"tags": [
"Content Api"
],
"summary": "Retrieve content by content reference or content guid",
"description": "",
"operationId": "getContent",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "referenceORguid",
"in": "path",
"description": "Content Reference or Guid to be loaded. Supports all reference formats (including work and provider IDs)",
"required": true,
"type": "string"
},
{
"name": "expand",
"type": "string",
"in": "query",
"description": "Comma-separated list of reference properties (Content References, Content Areas) which should have their content fetched in the response. Passing \"*\" will load content in all reference properties in the return."
},
{
"name": "Accept-Language",
"type": "string",
"in": "header",
"description": "Determines in which language the content should be retrieved. Example - en-US"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/ExpandedContentApiModel"
}
}
}
}
},
"/api/episerver/content/{reference}/children": {
"get": {
"tags": [
"Content Api"
],
"summary": "Retrieve child content of a content reference",
"description": "",
"operationId": "getChildren",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "reference",
"in": "path",
"description": "Content Reference for which to retrieve child content. Supports all reference formats (including work and provider IDs)",
"required": true,
"type": "string"
},
{
"name": "expand",
"type": "string",
"in": "query",
"description": "Comma-separated list of reference properties (Content References, Content Areas) which should have their content fetched in the response. Passing \"*\" will load content in all reference properties in the return."
},
{
"name": "Accept-Language",
"type": "string",
"in": "header",
"description": "Determines in which language the content should be retrieved. Example - en-US"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/ExpandedContentApiModel"
}
}
}
}
}
},
"/api/episerver/content/{reference}/ancestors": {
"get": {
"tags": [
"Content Api"
],
"summary": "Retrieve ancestor content for a content reference",
"description": "",
"operationId": "getAncestors",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "reference",
"in": "path",
"description": "Content Reference for which to retrieve ancestor content. Supports all reference formats (including work and provider IDs)",
"required": true,
"type": "string"
},
{
"name": "expand",
"type": "string",
"in": "query",
"description": "Comma-separated list of reference properties (Content References, Content Areas) which should have their content fetched in the response. Passing \"*\" will load content in all reference properties in the return."
},
{
"name": "Accept-Language",
"type": "string",
"in": "header",
"description": "Determines in which language the content should be retrieved. Example - en-US"
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/ExpandedContentApiModel"
}
}
}
}
}
},
"/api/episerver/site": {
"get": {
"tags": [
"Site Definition Api"
],
"summary": "Retrieve a list of sites in the system and their associated properties. By default, only the current site will be returned, unless the multi-site configuration flag is enabled in Configuration",
"description": "",
"operationId": "getSites",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Site"
}
}
}
}
}
}
},
"definitions": {
"ContentApiModel": {
"type": "object",
"properties": {
"ContentLink": {
"$ref": "#/definitions/ContentModelReference"
},
"Name": {
"type": "string",
"example": "Start Page"
},
"Language": {
"$ref": "#/definitions/LanguageModel"
},
"ExistingLanguages": {
"type": "array",
"items": {
"$ref": "#/definitions/LanguageModel"
}
},
"MasterLanguage": {
"$ref": "#/definitions/LanguageModel"
},
"ContentType": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"Page",
"StartPage"
]
},
"ParentLink": {
"$ref": "#/definitions/ContentModelReference"
},
"RouteSegment": {
"type": "string",
"example": "content-page"
},
"Url": {
"type": "string",
"example": "http://episerver.local/content-page/"
},
"Changed": {
"type": "string",
"format": "date-time"
},
"Created": {
"type": "string",
"format": "date-time"
},
"StartPublish": {
"type": "string",
"format": "date-time"
},
"StopPublish": {
"type": "string",
"format": "date-time",
"example": null
},
"Saved": {
"type": "string",
"format": "date-time"
},
"Status": {
"type": "string",
"example": "Published"
},
"Title": {
"type": "object",
"properties": {
"Value": {
"type": "string",
"example": "This is the Hello World Page"
},
"PropertyDataType": {
"type": "string",
"example": "PropertyString"
}
}
},
"MainBody": {
"type": "object",
"properties": {
"Value": {
"type": "string",
"example": "<p>Hello, World!"
},
"PropertyDataType": {
"type": "string",
"example": "PropertyXhtmlString"
}
}
},
"ReferencedContent": {
"type": "object",
"properties": {
"Value": {
"$ref": "#/definitions/ContentModelReference"
},
"PropertyDataType": {
"type": "string",
"example": "PropertyContentReference"
}
}
}
}
},
"ExpandedContentApiModel": {
"allOf": [
{
"$ref": "#/definitions/ContentApiModel"
},
{
"properties": {
"ReferencedContent": {
"type": "object",
"properties": {
"Value": {
"$ref": "#/definitions/ContentModelReference"
},
"ExpandedValue": {
"$ref": "#/definitions/ContentApiModel"
},
"PropertyDataType": {
"type": "string",
"example": "PropertyContentReference"
}
}
}
}
}
]
},
"ContentModelReference": {
"type": "object",
"properties": {
"Id": {
"type": "integer",
"format": "int32",
"example": 234
},
"WorkId": {
"type": "number",
"format": "int32"
},
"Guid": {
"type": "string",
"format": "guid",
"example": "2775f9ba-8a2b-46c8-b279-19764318cb48"
},
"ProviderName": {
"type": "string",
"format": "guid"
}
}
},
"SearchResponse": {
"type": "object",
"properties": {
"TotalMatching": {
"type": "number"
},
"Results": {
"type": "array",
"items": {
"$ref": "#/definitions/ExpandedContentApiModel"
}
}
}
},
"Site": {
"type": "object",
"properties": {
"Name": {
"type": "string",
"example": "Quicksilver"
},
"Id": {
"type": "string",
"format": "guid",
"example": "2775f9ba-8a2b-46c8-b279-19764318cb48"
},
"ContentRoots": {
"type": "object",
"properties": {
"ContentAssetsRoot": {
"$ref": "#/definitions/ContentModelReference"
},
"GlobalAssetsRoot": {
"$ref": "#/definitions/ContentModelReference"
},
"RootPage": {
"$ref": "#/definitions/ContentModelReference"
},
"WasteBasket": {
"$ref": "#/definitions/ContentModelReference"
},
"StartPage": {
"$ref": "#/definitions/ContentModelReference"
}
}
},
"Languages": {
"type": "array",
"items": {
"$ref": "#/definitions/SiteDefinitionLanguageModel"
}
}
}
},
"LanguageModel": {
"type": "object",
"properties": {
"DisplayName": {
"type": "string",
"example": "English"
},
"Name": {
"type": "string",
"example": "en"
}
}
},
"SiteDefinitionLanguageModel": {
"type": "object",
"properties": {
"DisplayName": {
"type": "string",
"example": "English"
},
"Name": {
"type": "string",
"example": "en"
},
"IsMasterLanguage": {
"type": "boolean",
"example": true
}
}
}
}
}
Wondering how can we get the swagger to set it up in Azure API Mangement Tool for EPiServer Content API?
https://world.episerver.com/documentation/developer-guides/CMS/Content/content-delivery-api/