Skip to content

Commit

Permalink
feat: add openapi documentation
Browse files Browse the repository at this point in the history
closes #2
  • Loading branch information
steveoh committed Aug 14, 2018
1 parent 85a4dec commit 7fd9a33
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 95 deletions.
1 change: 1 addition & 0 deletions api.mapserv.utah.gov/Controllers/CanaryController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace api.mapserv.utah.gov.Controllers
{
[ApiVersion("1.0")]
[ApiExplorerSettings(IgnoreApi = true)]
[Produces("application/json")]
public class CanaryController : Controller
{
Expand Down
61 changes: 28 additions & 33 deletions api.mapserv.utah.gov/Controllers/GeocodeAddressController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@

namespace api.mapserv.utah.gov.Controllers
{
/// <summary>
/// Geocoding API Methods
/// </summary>
/// <remarks>
/// API methods for finding a geolocation (x,y) for addresses.
/// </remarks>
[ApiController]
[ApiVersion("1.0")]
[Produces("application/json")]
Expand Down Expand Up @@ -53,10 +59,19 @@ public GeocodeAddressController(ParseAddressCommand parseAddressCommand, ParseZo
_reverseGeocodeCommand = reverseGeocodeAddressCommand;
}

/// <summary>
/// Finds the x, y location for an input address
/// </summary>
/// <remarks>Requires an API Key</remarks>
/// <response code="200">The address was geocoded successfully</response>
/// <response code="400">The input address was not well formed</response>
/// <response code="404">The input address was unable to be geocoded</response>
/// <param name="street">A Utah street address. eg: 326 east south temple st. Intersections are separated by `and`</param>
/// <param name="zone">A Utah municipality name or 5 digit zip code</param>
/// <param name="options"></param>
[HttpGet]
[Produces("application/json")]
[ProducesResponseType(200, Type = typeof(ApiResponseContainer<GeocodeAddressApiResponse>))]
[ProducesResponseType(400, Type = typeof(ApiResponseContainer<GeocodeAddressApiResponse>))]
[ProducesResponseType(400, Type = typeof(ApiResponseContainer))]
[ProducesResponseType(404, Type = typeof(ApiResponseContainer))]
[Route("api/v{version:apiVersion}/geocode/{street}/{zone}")]
public async Task<ObjectResult> Get(string street, string zone, [FromQuery] GeocodingOptions options)
Expand Down Expand Up @@ -226,43 +241,23 @@ public async Task<ObjectResult> Get(string street, string zone, [FromQuery] Geoc
});
}

/// <summary>
/// Finds the nearest address to the input location
/// </summary>
/// <remarks>Requires an API Key</remarks>
/// <response code="200">An address was found near the input location</response>
/// <response code="400">The input location was not well formed</response>
/// <response code="404">No house address could be found within the distance supplied from the input location</response>
/// <param name="x">A geographic coordinate representing the longitude or easting</param>
/// <param name="y">A geographic coordinate representing the latitdue or northing</param>
/// <param name="options"></param>
[HttpGet]
[Produces("application/json")]
[ProducesResponseType(200, Type = typeof(ApiResponseContainer<ReverseGeocodeApiResponse>))]
[ProducesResponseType(400, Type = typeof(ApiResponseContainer<ReverseGeocodeApiResponse>))]
[ProducesResponseType(400, Type = typeof(ApiResponseContainer))]
[ProducesResponseType(404, Type = typeof(ApiResponseContainer))]
[Route("api/v{version:apiVersion}/geocode/reverse/{x:double}/{y:double}")]
public async Task<ObjectResult> Reverse(double x, double y, [FromQuery] ReverseGeocodingOptions options)
{
//#region validation

//var errors = "";
//if (!xIn.HasValue)
//{
// errors = "X is empty. ";
//}

//if (!yIn.HasValue)
//{
// errors += "Y is emtpy";
//}

//if (errors.Length > 0)
//{
// Log.Debug("Bad reverse geocode request", errors);

// return BadRequest(new ApiResponseContainer<ReverseGeocodeApiResponse>
// {
// Status = (int)HttpStatusCode.BadRequest,
// Message = errors
// });
//}

//#endregion

//var x = xIn.Value;
//var y = yIn.Value;

if (options.SpatialReference != 26912)
{
_reprojectCommnd.Initialize(new ReprojectPointsCommand.PointProjectQueryArgs(options.SpatialReference, 26912, new [] { x, y }));
Expand Down
1 change: 1 addition & 0 deletions api.mapserv.utah.gov/Controllers/ValuesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace api.mapserv.utah.gov.Controllers
{
[Route("api/[controller]")]
[ApiExplorerSettings(IgnoreApi = true)]
public class ValuesController : Controller
{
// GET api/values
Expand Down
51 changes: 20 additions & 31 deletions api.mapserv.utah.gov/Models/RequestOptions/GeocodingOptions.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,48 @@
using api.mapserv.utah.gov.Models.Constants;
using System.ComponentModel;
using api.mapserv.utah.gov.Models.Constants;

namespace api.mapserv.utah.gov.Models.RequestOptions
{
/// <summary>
/// The options available for geocoding
/// </summary>
public class GeocodingOptions : OptionBase
public class GeocodingOptions : ProjectableOptions
{
/// <summary>
/// Gets or sets the accept score for the address.
/// A score from 0 to 100 used to rank geocode candidates.
/// Default: 70
/// </summary>
/// <value>
/// The accept score defaults to 70 in the GeocodeOptionsModelBinder.
/// </value>
[DefaultValue(70)]
public int AcceptScore { get; set; } = 70;

/// <summary>
/// Gets or sets the suggest count for how many address candidates to return.
/// The count of candidates to return beside the highest match candidate.
/// Default: 0
/// </summary>
/// <value>
/// The suggest count.
/// </value>
[DefaultValue(0)]
public int Suggest { get; set; } = 0;

/// <summary>
/// Gets or sets the locators.
/// How the service will attempt to locate the address.
/// All is a combination of address point locators and road centerline locators; This will offer the best results.
/// addressPoints will only geocode on address points and roadCenterlines will only geocode on road centerlines.
/// Default: All.
/// </summary>
/// <value>
/// The locators to grab for geocoding.
/// </value>
[DefaultValue(LocatorType.All)]
public LocatorType Locators { get; set; } = LocatorType.All;

/// <summary>
/// Gets or sets the spatial reference well known id.
/// How the service will handle P.O. Boxes. True will return the coordinates of the post office where the mail is delivered. False will return no match. P.O. Boxes can only be processed if the zone is a zip code. If a place name is used in the zone the geocode will return no match.
/// Default: true.
/// </summary>
/// <value>
/// The wkid.
/// </value>
public int SpatialReference { get; set; } = 26912;

/// <summary>
/// Instructs the API to try to find the post office or delivery point for a post office address.
/// </summary>
/// <value>
/// <c>true</c> if should geocode po box; otherwise, <c>false</c>.
/// </value>
[DefaultValue(true)]
public bool PoBox { get; set; } = true;

/// <summary>
/// Instructs the api to return the difference between the match address and the next best option.
/// This is only calculated if this property is true and the suggest count is 0
/// Request the api to calculate the difference in score between the match address and the top suggestion. This flag is only calculated and returned when suggest=0 and there is a top suggestion. If there is no top suggestion, the property is not sent. If the value is 0, then you have a tie and should investigate the addresses by using the suggest items.
/// Default: false.
/// </summary>
/// <value>
/// <c>true</c> if should calculate the sccore difference; otherwise, <c>false</c>.
/// </value>
[DefaultValue(false)]
public bool ScoreDifference { get; set; } = false;

public override string ToString() => $"AcceptScore: {AcceptScore}, SuggestCount: {Suggest}, JsonFormat: {Format}, Type: {Locators}, wkid: {SpatialReference} ";
Expand Down
29 changes: 14 additions & 15 deletions api.mapserv.utah.gov/Models/RequestOptions/OptionBase.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
using api.mapserv.utah.gov.Models.Constants;
using System.ComponentModel;
using api.mapserv.utah.gov.Models.Constants;

namespace api.mapserv.utah.gov.Models.RequestOptions
{
public class OptionBase
{
public OptionBase()
{
Format = JsonFormat.None;
}
public class OptionBase
{
public OptionBase()
{
Format = JsonFormat.None;
}

/// <summary>
/// Gets or sets the json format for the geometry response.
/// </summary>
/// <value>
/// The json format.
/// </value>
public JsonFormat Format { get; set; }
}
/// <summary>
/// The format of the resulting address. esri json will easily parse into an esri.Graphic for display on a map and geojson will easily parse into a feature for use in many open source projects. If this value is omitted, the default json will be returned.
/// </summary>
[DefaultValue(JsonFormat.None)]
public JsonFormat Format { get; set; }
}
}
17 changes: 17 additions & 0 deletions api.mapserv.utah.gov/Models/RequestOptions/ProjectableOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.ComponentModel;

namespace api.mapserv.utah.gov.Models.RequestOptions
{
public class ProjectableOptions : OptionBase
{
/// <summary>
/// The spatial reference for the output and input geometries.
/// Choose any of the <abbr title = "Well-known Id">wkid</abbr>'s from the <a href= "http://resources.arcgis.com/en/help/main/10.1/018z/pdf/geographic_coordinate_systems.pdf"> Geographic Coordinate System wkid reference</a> or <a href="http://resources.arcgis.com/en/help/main/10.1/018z/pdf/projected_coordinate_systems.pdf"> Projected Coordinate System wkid reference</a>.
/// Default: 26912
/// </summary>
[DefaultValue(26912)]
public int SpatialReference { get; set; } = 26912;

}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
namespace api.mapserv.utah.gov.Models.RequestOptions
using System.ComponentModel;

namespace api.mapserv.utah.gov.Models.RequestOptions
{
public class ReverseGeocodingOptions : OptionBase
public class ReverseGeocodingOptions : ProjectableOptions
{
/// <summary>
/// Gets or sets the distance in meters from the point to find an address.
/// The distance in meters from the input location to look for an address.
/// Default: 5
/// </summary>
/// <value>
/// The distance in meters.
/// </value>
[DefaultValue(5)]
public double Distance { get; set; } = 5;

/// <summary>
/// Gets or sets the spatial reference well known id for the input coordinates.
/// </summary>
/// <value>
/// The wkid.
/// </value>
public int SpatialReference { get; set; } = 26912;
}
}
54 changes: 52 additions & 2 deletions api.mapserv.utah.gov/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using api.mapserv.utah.gov.Extensions;
using System;
using System.IO;
using System.Reflection;
using api.mapserv.utah.gov.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Swashbuckle.AspNetCore.Swagger;
using WebApiContrib.Core.Formatter.Jsonp;

namespace api.mapserv.utah.gov
Expand All @@ -28,7 +32,8 @@ public Startup(IConfiguration configuration, IHostingEnvironment env, ILoggerFac
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddMvc(options => {
services.AddMvc(options =>
{
options.AddApiResponseFormatters();
options.AddJsonpOutputFormatter();
})
Expand All @@ -45,6 +50,37 @@ public void ConfigureServices(IServiceCollection services)

services.UseOptions(Configuration);
services.UseDi();

services.AddSwaggerGen(c =>
{
c.EnableAnnotations();
c.DescribeAllParametersInCamelCase();
c.DescribeAllEnumsAsStrings();
c.DescribeStringEnumsInCamelCase();
c.SwaggerDoc("v1", new Info
{
Version = "v1",
Title = "AGRC WebAPI : OpenAPI Documentation",
Description = "OpenAPI Documentation",
Contact = new Contact
{
Name = "AGRC",
Email = string.Empty,
Url = "https://github.com/agrc/api.mapserv.utah.gov"
},
License = new License
{
Name = "MIT",
Url = "https://github.com/agrc/api.mapserv.utah.gov/blob/master/LICENSE"
}
});
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand All @@ -55,6 +91,20 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env)
app.UseDeveloperExceptionPage();
}

app.UseSwagger(c => {
c.RouteTemplate = "openapi/{documentName}/api.json";
});

app.UseSwaggerUI(c =>
{
c.DocumentTitle = "AGRC WebAPI OpenAPI Documentation";
c.RoutePrefix = "openapi";
c.SwaggerEndpoint("/openapi/v1/api.json", "v1");
c.SupportedSubmitMethods(new SubmitMethod[] {});
c.EnableDeepLinking();
c.DocExpansion(DocExpansion.List);
});

app.UseMvc();
}
}
Expand Down
6 changes: 6 additions & 0 deletions api.mapserv.utah.gov/api.mapserv.utah.gov.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<LangVersion>Latest</LangVersion>
</PropertyGroup>
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
Expand All @@ -29,6 +33,8 @@
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="GeoJSON.Net" Version="1.1.64" />
<PackageReference Include="WebApiContrib.Core.Formatter.Jsonp" Version="2.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="3.0.0" />
</ItemGroup>

</Project>

0 comments on commit 7fd9a33

Please sign in to comment.