Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace Swashbuckle.Swagger.Annotations
{
public class SwaggerDescriptionAttribute : Attribute
{
public SwaggerDescriptionAttribute(string description = null, string summary = null)
{
Description = description;
Summary = summary;
}

public string Description { get; set; }
public string Summary { get; set; }
}
}
12 changes: 12 additions & 0 deletions Swashbuckle.Core/Swagger/SchemaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json.Serialization;
using Swashbuckle.Swagger.Annotations;

namespace Swashbuckle.Swagger
{
Expand Down Expand Up @@ -46,6 +47,17 @@ public static Schema WithValidationProperties(this Schema schema, JsonProperty j
return schema;
}

public static Schema WithDescriptionProperty(this Schema schema, JsonProperty jsonProperty)
{
var propInfo = jsonProperty.PropertyInfo();
if (propInfo == null)
return schema;

var attrib = propInfo.GetCustomAttributes(false).OfType<SwaggerDescriptionAttribute>().FirstOrDefault();
schema.description = attrib != null ? attrib.Description : null;
return schema;
}

public static void PopulateFrom(this PartialSchema partialSchema, Schema schema)
{
if (schema == null) return;
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.Core/Swagger/SchemaRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ private Schema CreateObjectSchema(JsonObjectContract jsonContract)
.Where(p => !(_ignoreObsoleteProperties && p.IsObsolete()))
.ToDictionary(
prop => prop.PropertyName,
prop => CreateInlineSchema(prop.PropertyType).WithValidationProperties(prop)
prop => CreateInlineSchema(prop.PropertyType).WithValidationProperties(prop).WithDescriptionProperty(prop)
);

var required = jsonContract.Properties.Where(prop => prop.IsRequired())
Expand Down
18 changes: 12 additions & 6 deletions Swashbuckle.Core/Swagger/SwaggerGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
using System.Web.Http.Description;
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Net.Http.Formatting;
using System.Net.Http;
using System.Threading;
using Swashbuckle.Swagger.Annotations;

namespace Swashbuckle.Swagger
{
Expand Down Expand Up @@ -67,7 +65,7 @@ public SwaggerDocument GetSwagger(string rootUrl, string apiVersion)
securityDefinitions = _options.SecurityDefinitions
};

foreach(var filter in _options.DocumentFilters)
foreach (var filter in _options.DocumentFilters)
{
filter.Apply(swaggerDoc, schemaRegistry, _apiExplorer);
}
Expand Down Expand Up @@ -142,6 +140,7 @@ private Operation CreateOperation(ApiDescription apiDesc, SchemaRegistry schemaR
})
.ToList();

var description = apiDesc.ActionDescriptor.GetCustomAttributes<SwaggerDescriptionAttribute>().FirstOrDefault();
var responses = new Dictionary<string, Response>();
var responseType = apiDesc.ResponseType();
if (responseType == null || responseType == typeof(void))
Expand All @@ -152,12 +151,14 @@ private Operation CreateOperation(ApiDescription apiDesc, SchemaRegistry schemaR
var operation = new Operation
{
tags = new[] { _options.GroupingKeySelector(apiDesc) },
description = description != null ? description.Description : null,
summary = description != null ? description.Summary : null,
operationId = apiDesc.FriendlyId(),
produces = apiDesc.Produces().ToList(),
consumes = apiDesc.Consumes().ToList(),
parameters = parameters.Any() ? parameters : null, // parameters can be null but not empty
responses = responses,
deprecated = apiDesc.IsObsolete() ? true : (bool?) null
deprecated = apiDesc.IsObsolete() ? true : (bool?)null
};

foreach (var filter in _options.OperationFilters)
Expand Down Expand Up @@ -191,12 +192,17 @@ private Parameter CreateParameter(string location, ApiParameterDescription param
{
parameter.type = "string";
parameter.required = true;
return parameter;
return parameter;
}

parameter.required = location == "path" || !paramDesc.ParameterDescriptor.IsOptional;
parameter.@default = paramDesc.ParameterDescriptor.DefaultValue;

var description = paramDesc.ParameterDescriptor.GetCustomAttributes<SwaggerDescriptionAttribute>().FirstOrDefault();
if (description != null)
{
parameter.description = description.Description;
}
var schema = schemaRegistry.GetOrRegister(paramDesc.ParameterDescriptor.ParameterType);
if (parameter.@in == "body")
parameter.schema = schema;
Expand Down
1 change: 1 addition & 0 deletions Swashbuckle.Core/Swashbuckle.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="Swagger\Annotations\ApplySwaggerOperationAttributes.cs" />
<Compile Include="Swagger\Annotations\ApplySwaggerSchemaFilterAttributes.cs" />
<Compile Include="Swagger\Annotations\ApplySwaggerOperationFilterAttributes.cs" />
<Compile Include="Swagger\Annotations\SwaggerDescriptionAttribute.cs" />
<Compile Include="Swagger\Annotations\SwaggerOperationAttribute.cs" />
<Compile Include="Swagger\Annotations\SwaggerSchemaFilterAttribute.cs" />
<Compile Include="Swagger\Annotations\SwaggerOperationFilterAttribute.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public Message GetById(int id)

[HttpPut]
[SwaggerOperation("UpdateMessage", Tags = new[] { "messages" }, Schemes = new[] { "ws" })]
public void Put(int id, Message message)

public void Put([SwaggerDescription("param description")]int id, Message message)
{
throw new NotImplementedException();
}
Expand All @@ -41,6 +42,7 @@ public void Put(int id, Message message)
[SwaggerSchemaFilter(typeof(AddMessageDefault))]
public class Message
{
[SwaggerDescription("param model description")]
public string Title { get; set; }
public string Content { get; set; }
}
Expand Down
5 changes: 3 additions & 2 deletions Swashbuckle.Dummy.SelfHost/Swashbuckle.Dummy.SelfHost.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand All @@ -9,10 +9,11 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Swashbuckle.Dummy.SelfHost</RootNamespace>
<AssemblyName>Swashbuckle.Dummy.SelfHost</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down
16 changes: 8 additions & 8 deletions Swashbuckle.Dummy.SelfHost/app.config
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.2.0" newVersion="5.2.2.0" />
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.2.0" newVersion="5.2.2.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.2.0" newVersion="5.2.2.0" />
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.2.2.0" newVersion="5.2.2.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration>
9 changes: 9 additions & 0 deletions Swashbuckle.Tests/Swagger/AnnotationsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,14 @@ public void It_supports_per_action_filters_via_swagger_operation_filter_attribut

Assert.AreEqual(expected.ToString(), responseExamples.ToString());
}

[Test]
public void It_has_parameter_descriptions()
{
var swagger = GetContent<JObject>("http://tempuri.org/swagger/docs/v1");
var description = (string)swagger["paths"]["/swaggerannotated/{id}"]["put"]["parameters"][0]["description"];

Assert.AreEqual("param description", description);
}
}
}