Skip to content

Instantly share code, notes, and snippets.

@cezarypiatek
Last active October 22, 2023 16:33
Show Gist options
  • Save cezarypiatek/d7cd41a0e7bf484e07a5ea9ea119c757 to your computer and use it in GitHub Desktop.
Save cezarypiatek/d7cd41a0e7bf484e07a5ea9ea119c757 to your computer and use it in GitHub Desktop.
Example provider for Swashbuckle
services.AddSwaggerGen(c =>
{
c.UseExampleFilter(e =>
{
e.DefineExample<AuthenticationController>(con => con.Login(new LoginCredentials
{
Login = "cezarypiatek",
Password = "secret"
}));
e.DefineExamples<DiagnosticController>(ec =>
{
ec.DefineExample(con => con.StoreEventData(new EventStorageModel
{
EventType = "GeneralEvent",
Details = new EventStorageDetails()
{
Title = "Greeting",
Message = "Hello world"
}
}));
});
});
});
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using JetBrains.Annotations;
namespace SwaggerHelpers
{
public class ExampleInvocationContainer<TController>:IEnumerable<Expression<Action<TController>>>
{
private readonly IList<Expression<Action<TController>>> sampleInvocations = new List<Expression<Action<TController>>>();
public void DefineExample([NotNull] Expression<Action<TController>> example)
{
this.sampleInvocations.Add(example);
}
/// <inheritdoc />
public IEnumerator<Expression<Action<TController>>> GetEnumerator()
{
return this.sampleInvocations.GetEnumerator();
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
using System.Linq;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.Controllers;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace SwaggerHelpers
{
[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)]
public class ExampleOperationFilter: IOperationFilter
{
private readonly ExampleOperationFilterConfig config;
/// <inheritdoc />
public ExampleOperationFilter(ExampleOperationFilterConfig config)
{
this.config = config;
}
/// <inheritdoc />
public void Apply([NotNull] Operation operation, [NotNull] OperationFilterContext context)
{
if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor actionDescriptor && operation.Parameters != null)
{
if (this.config.TryGetActionParametersExamples(actionDescriptor, out var parametersValues))
{
foreach (var parameter in operation.Parameters.OfType<BodyParameter>())
{
if (parametersValues.TryGetValue(parameter.Name, out var parameterValue))
{
parameter.Extensions.Add("default", parameterValue);
}
}
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.Controllers;
using Newtonsoft.Json;
namespace SwaggerHelpers
{
public class ExampleOperationFilterConfig
{
private readonly IDictionary<string, Dictionary<string,string>> invocationExamples = new Dictionary<string, Dictionary<string,string>>();
[NotNull, Pure]
private static Dictionary<string, object> BuildParameterValuesFromExpression([NotNull] MethodCallExpression call)
{
var parameterValues = new Dictionary<string, object>();
var parameters = call.Method.GetParameters();
if (parameters.Length > 0)
{
for (int index = 0; index < parameters.Length; index++)
{
var parameterExpression = call.Arguments[index];
var value = Expression.Lambda(parameterExpression)
.Compile()
.DynamicInvoke();
parameterValues.Add(parameters[index].Name, value);
}
}
return parameterValues;
}
public void DefineExample<TController>([NotNull] Expression<Action<TController>> sampleInvocation)
{
var methodCall= (MethodCallExpression) sampleInvocation.Body;
var actionName = methodCall.Method.Name;
var controllerName = typeof(TController).Name.Replace("Controller", "");
var key = GetActionKey(controllerName, actionName);
this.invocationExamples[key] = BuildParameterValuesFromExpression(methodCall)
.ToDictionary(x=>x.Key, x=> JsonConvert.SerializeObject(x.Value, Formatting.Indented));
}
public void DefineExamples<TController>([NotNull] Action<ExampleInvocationContainer<TController>> configure)
{
var exampleContainer = new ExampleInvocationContainer<TController>();
configure(exampleContainer);
foreach (var example in exampleContainer)
{
this.DefineExample(example);
}
}
[NotNull, Pure]
private static string GetActionKey(string controllerName, string actionName)
{
return $"{controllerName}_{actionName}";
}
[Pure]
public bool TryGetActionParametersExamples([NotNull] ControllerActionDescriptor c, out Dictionary<string, string> parametersValues)
{
var actionKey = ExampleOperationFilterConfig.GetActionKey(c.ControllerName, c.ActionName);
return this.invocationExamples.TryGetValue(actionKey, out parametersValues);
}
}
}
using System;
using JetBrains.Annotations;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace SwaggerHelpers
{
public static class ExmpleOperationFilterExtensions
{
public static void UseExampleFilter([NotNull] this SwaggerGenOptions app, [NotNull] Action<ExampleOperationFilterConfig> configure)
{
var configuration = new ExampleOperationFilterConfig();
configure(configuration);
app.OperationFilter<ExampleOperationFilter>(configuration);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment