Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Commit 3cd6d3e

Browse files
committed
Adding Api Explorer
1 parent 6600e68 commit 3cd6d3e

File tree

58 files changed

+3010
-14
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3010
-14
lines changed

Mvc.sln

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 14
4-
VisualStudioVersion = 14.0.22115.0
4+
VisualStudioVersion = 14.0.22013.1
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
77
EndProject
@@ -80,6 +80,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "XmlSerializerWebSite", "tes
8080
EndProject
8181
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "UrlHelperWebSite", "test\WebSites\UrlHelperWebSite\UrlHelperWebSite.kproj", "{A192E504-2881-41DC-90D1-B7F1DD1134E8}"
8282
EndProject
83+
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ApiExplorerWebSite", "test\WebSites\ApiExplorerWebSite\ApiExplorerWebSite.kproj", "{61061528-071E-424E-965A-07BCC2F02672}"
84+
EndProject
8385
Global
8486
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8587
Debug|Any CPU = Debug|Any CPU
@@ -410,6 +412,16 @@ Global
410412
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
411413
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
412414
{A192E504-2881-41DC-90D1-B7F1DD1134E8}.Release|x86.ActiveCfg = Release|Any CPU
415+
{61061528-071E-424E-965A-07BCC2F02672}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
416+
{61061528-071E-424E-965A-07BCC2F02672}.Debug|Any CPU.Build.0 = Debug|Any CPU
417+
{61061528-071E-424E-965A-07BCC2F02672}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
418+
{61061528-071E-424E-965A-07BCC2F02672}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
419+
{61061528-071E-424E-965A-07BCC2F02672}.Debug|x86.ActiveCfg = Debug|Any CPU
420+
{61061528-071E-424E-965A-07BCC2F02672}.Release|Any CPU.ActiveCfg = Release|Any CPU
421+
{61061528-071E-424E-965A-07BCC2F02672}.Release|Any CPU.Build.0 = Release|Any CPU
422+
{61061528-071E-424E-965A-07BCC2F02672}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
423+
{61061528-071E-424E-965A-07BCC2F02672}.Release|Mixed Platforms.Build.0 = Release|Any CPU
424+
{61061528-071E-424E-965A-07BCC2F02672}.Release|x86.ActiveCfg = Release|Any CPU
413425
EndGlobalSection
414426
GlobalSection(SolutionProperties) = preSolution
415427
HideSolutionNode = FALSE
@@ -448,5 +460,6 @@ Global
448460
{1976AC4A-FEA4-4587-A158-D9F79736D2B6} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
449461
{96107AC0-18E2-474D-BAB4-2FFF2185FBCD} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
450462
{A192E504-2881-41DC-90D1-B7F1DD1134E8} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
463+
{61061528-071E-424E-965A-07BCC2F02672} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
451464
EndGlobalSection
452465
EndGlobal
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNet.Mvc;
5+
using Microsoft.AspNet.Mvc.Description;
6+
7+
namespace MvcSample.Web
8+
{
9+
[Route("ApiExplorer")]
10+
public class ApiExplorerController : Controller
11+
{
12+
[Activate]
13+
public IApiDescriptionGroupCollectionProvider Provider { get; set; }
14+
15+
[HttpGet]
16+
public IActionResult All()
17+
{
18+
var descriptions = Provider.ApiDescriptionGroups.Items;
19+
return View(descriptions);
20+
}
21+
}
22+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.api-description {
2+
margin: 10px 0px 10px 0px;
3+
padding: 5px;
4+
}
5+
6+
.api-description hr {
7+
border: 0px;
8+
border-top: 1px solid #D44B4B;
9+
margin: 0px;
10+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Microsoft.AspNet.Mvc;
2+
using System;
3+
using System.Collections.Generic;
4+
5+
namespace MvcSample.Web.ApiExplorerSamples
6+
{
7+
[ApiExplorerSettings(GroupName = "Admin API")]
8+
[Route("api/Admin/Products")]
9+
public class ProductsAdminController : Controller
10+
{
11+
[HttpPut]
12+
public void AddProduct([FromBody] Product product)
13+
{
14+
}
15+
16+
[HttpPost("{id}")]
17+
public void UpdateProduct([FromBody] Product product)
18+
{
19+
}
20+
21+
[HttpPost("{id}/Stock")]
22+
public void SetQuantityInStock(int id, int quantity)
23+
{
24+
}
25+
26+
[HttpPost("{id}/Price")]
27+
public void SetPrice(int id, decimal price)
28+
{
29+
}
30+
31+
[Produces("application/json", "application/xml")]
32+
[HttpGet("{id}/Orders")]
33+
public IEnumerable<ProductOrderConfirmation> GetOrders(DateTime? fromData = null, DateTime? toDate = null)
34+
{
35+
return null;
36+
}
37+
}
38+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using Microsoft.AspNet.Mvc;
3+
using System.Collections.Generic;
4+
5+
namespace MvcSample.Web.ApiExplorerSamples
6+
{
7+
[ApiExplorerSettings(GroupName = "Public API")]
8+
[Produces("application/json")]
9+
[Route("api/Products")]
10+
public class ProductsController : Controller
11+
{
12+
[HttpGet("{id}")]
13+
public Product GetById(int id)
14+
{
15+
return null;
16+
}
17+
18+
[HttpGet("Search/{name}")]
19+
public IEnumerable<Product> SearchByName(string name)
20+
{
21+
return null;
22+
}
23+
24+
[Produces("application/json", Type = typeof(ProductOrderConfirmation))]
25+
[HttpPut("{id}/Buy")]
26+
public IActionResult Buy(int projectId, int quantity = 1)
27+
{
28+
return null;
29+
}
30+
}
31+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace MvcSample.Web.ApiExplorerSamples
4+
{
5+
public class Product
6+
{
7+
public string Name { get; set; }
8+
9+
public string Description { get; set; }
10+
11+
public decimal Price { get; set; }
12+
}
13+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace MvcSample.Web.ApiExplorerSamples
4+
{
5+
public class ProductOrderConfirmation
6+
{
7+
public Product Product { get; set; }
8+
9+
public decimal PricePerUnit { get; set; }
10+
11+
public int Quantity { get; set; }
12+
13+
public decimal TotalPrice { get; set; }
14+
}
15+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@using Microsoft.AspNet.Mvc.Description
2+
@model IReadOnlyList<ApiDescriptionGroup>
3+
4+
@section header
5+
{
6+
<link rel="stylesheet" href="~/Content/api-description.css" />
7+
}
8+
9+
<div style="padding: 50px 0px 0px 0px">
10+
11+
@foreach (var group in Model)
12+
{
13+
<div class="row">
14+
<h1>Group: @group.GroupName</h1>
15+
16+
@foreach (var item in group.Items)
17+
{
18+
await Html.RenderPartialAsync("_ApiDescription", item);
19+
}
20+
21+
</div>
22+
}
23+
</div>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@using Microsoft.AspNet.Mvc.Description
2+
@model ApiDescription
3+
4+
<div class="api-description">
5+
<h4>@(Model.HttpMethod ?? "*") - @(Model.RelativePath ?? "Unknown Url")</h4>
6+
<hr />
7+
<h5>For action: @Model.ActionDescriptor.DisplayName</h5>
8+
<p>Return Type: @(Model.ResponseType?.FullName ?? "Unknown Type")</p>
9+
10+
@if (Model.ParameterDescriptions.Count > 0)
11+
{
12+
<p>Parameters:</p>
13+
<ul>
14+
@foreach (var parameter in Model.ParameterDescriptions)
15+
{
16+
<li>@parameter.Name - @parameter.Type.FullName - @parameter.Source.ToString()</li>
17+
}
18+
</ul>
19+
}
20+
21+
@if (Model.SupportedResponseFormats.Count > 0)
22+
{
23+
<p>Response Formats:</p>
24+
<ul>
25+
@foreach(var response in Model.SupportedResponseFormats)
26+
{
27+
<li>@response.MediaType.RawValue - @response.Formatter.GetType().Name</li>
28+
}
29+
</ul>
30+
}
31+
</div>

src/Microsoft.AspNet.Mvc.Core/ActionDescriptor.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class ActionDescriptor
1111
{
1212
public ActionDescriptor()
1313
{
14+
Properties = new Dictionary<object, object>();
1415
RouteValueDefaults = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
1516
}
1617

@@ -34,5 +35,10 @@ public ActionDescriptor()
3435
/// A friendly name for this action.
3536
/// </summary>
3637
public virtual string DisplayName { get; set; }
38+
39+
/// <summary>
40+
/// Stores arbitrary metadata properties associated with the <see cref="ActionDescriptor"/>.
41+
/// </summary>
42+
public IDictionary<object, object> Properties { get; private set; }
3743
}
3844
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNet.Mvc
5+
{
6+
/// <summary>
7+
/// Extension methods for <see cref="ActionDescriptor"/>.
8+
/// </summary>
9+
public static class ActionDescriptorExtensions
10+
{
11+
/// <summary>
12+
/// Gets the value of a property from the <see cref="ActionDescriptor.Properties"/> collection
13+
/// using the provided value of <typeparamref name="T"/> as the key.
14+
/// </summary>
15+
/// <typeparam name="T">The type of the property.</typeparam>
16+
/// <param name="actionDescriptor">The action descriptor.</param>
17+
/// <returns>The property or the default value of <typeparamref name="T"/>.</returns>
18+
public static T GetProperty<T>([NotNull] this ActionDescriptor actionDescriptor)
19+
{
20+
object value;
21+
if (actionDescriptor.Properties.TryGetValue(typeof(T), out value))
22+
{
23+
return (T)value;
24+
}
25+
else
26+
{
27+
return default(T);
28+
}
29+
}
30+
31+
/// <summary>
32+
/// Sets the value of an property in the <see cref="ActionDescriptor.Properties"/> collection using
33+
/// the provided value of <typeparamref name="T"/> as the key.
34+
/// </summary>
35+
/// <typeparam name="T">The type of the property.</typeparam>
36+
/// <param name="actionDescriptor">The action descriptor.</param>
37+
/// <param name="value">The value of the property.</param>
38+
public static void SetProperty<T>([NotNull] this ActionDescriptor actionDescriptor, [NotNull] T value)
39+
{
40+
actionDescriptor.Properties[typeof(T)] = value;
41+
}
42+
}
43+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using Microsoft.AspNet.Mvc.ModelBinding;
7+
8+
namespace Microsoft.AspNet.Mvc.Description
9+
{
10+
/// <summary>
11+
/// Represents an API exposed by this application.
12+
/// </summary>
13+
public class ApiDescription
14+
{
15+
/// <summary>
16+
/// Creates a new instance of <see cref="ApiDescription"/>.
17+
/// </summary>
18+
public ApiDescription()
19+
{
20+
Properties = new Dictionary<object, object>();
21+
ParameterDescriptions = new List<ApiParameterDescription>();
22+
SupportedResponseFormats = new List<ApiResponseFormat>();
23+
}
24+
25+
/// <summary>
26+
/// The <see cref="ActionDescriptor"/> for this api.
27+
/// </summary>
28+
public ActionDescriptor ActionDescriptor { get; set; }
29+
30+
/// <summary>
31+
/// The group name for this api.
32+
/// </summary>
33+
public string GroupName { get; set; }
34+
35+
/// <summary>
36+
/// The supported HTTP method for this api, or null if all HTTP methods are supported.
37+
/// </summary>
38+
public string HttpMethod { get; set; }
39+
40+
/// <summary>
41+
/// The list of <see cref="ApiParameterDescription"/> for this api.
42+
/// </summary>
43+
public List<ApiParameterDescription> ParameterDescriptions { get; private set; }
44+
45+
/// <summary>
46+
/// Stores arbitrary metadata properties associated with the <see cref="ApiDescription"/>.
47+
/// </summary>
48+
public IDictionary<object, object> Properties { get; private set; }
49+
50+
/// <summary>
51+
/// The relative url path template (relative to application root) for this api.
52+
/// </summary>
53+
public string RelativePath { get; set; }
54+
55+
/// <summary>
56+
/// The <see cref="ModelMetadata"/> for the <see cref="ResponseType"/> or null.
57+
/// </summary>
58+
/// <remarks>
59+
/// Will be null if <see cref="ResponseType"/> is null.
60+
/// </remarks>
61+
public ModelMetadata ResponseModelMetadata { get; set; }
62+
63+
/// <summary>
64+
/// The CLR data type of the response or null.
65+
/// </summary>
66+
/// <remarks>
67+
/// Will be null if the action returns no response, or if the response type is unclear. Use
68+
/// <see cref="ProducesAttribute"/> on an action method to specify a response type.
69+
/// </remarks>
70+
public Type ResponseType { get; set; }
71+
72+
/// <summary>
73+
/// A list of possible formats for a response.
74+
/// </summary>
75+
/// <remarks>
76+
/// Will be empty if the action returns no response, or if the response type is unclear. Use
77+
/// <see cref="ProducesAttribute"/> on an action method to specify a response type.
78+
/// </remarks>
79+
public IList<ApiResponseFormat> SupportedResponseFormats { get; private set; }
80+
}
81+
}

0 commit comments

Comments
 (0)