Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Starting work on HttpClientFactory documentation #5483

Merged
merged 44 commits into from
May 2, 2018
Merged
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1b897ac
Starting work on HttpClientFactory documentation (WIP)
stevejgordon Feb 15, 2018
37a56fb
Fixing some minor issues
stevejgordon Feb 15, 2018
0523d99
Updating per initial feedback
stevejgordon Feb 16, 2018
ca0cc90
Adding refit example
stevejgordon Feb 16, 2018
7026d16
Further feedback adjustments
stevejgordon Feb 16, 2018
ed1b3dd
Adding delegating handler middleware section
stevejgordon Feb 16, 2018
bfed490
Minor typo
stevejgordon Feb 16, 2018
812cf28
Initial Polly example
stevejgordon Feb 16, 2018
86e239d
Updating with latest feedback
stevejgordon Feb 19, 2018
ec14f81
Pass to remove you/your + improve readability and clarity
stevejgordon Feb 19, 2018
d527081
Additional tidy-up
stevejgordon Feb 19, 2018
ad34a62
Edits for latest feedback
stevejgordon Feb 21, 2018
37a5deb
UE pass
scottaddie Feb 21, 2018
b5aa44b
Snippet fixes
stevejgordon Feb 22, 2018
135a6e1
Add ms.custom metadata
scottaddie Feb 22, 2018
b62b134
Adding WIP sample project
stevejgordon Feb 23, 2018
c71f194
Minor edits to Fundamentals index page
scottaddie Feb 23, 2018
a7e1c51
Relocate master TOC link
scottaddie Feb 23, 2018
590150d
Feedback and sample update to 2.1 preview
stevejgordon Feb 27, 2018
567afbb
Fixing some missed HttpClientFactory items
stevejgordon Mar 1, 2018
5d18655
Initial snippets from sample
stevejgordon Mar 1, 2018
2251cb9
Fixing a copy/paste mistake
stevejgordon Mar 1, 2018
c8b6438
fixing code link
stevejgordon Mar 1, 2018
aaf26d3
Remove gerund from title
scottaddie Mar 1, 2018
c9d0daf
Fix wording in the description metadata value
scottaddie Mar 1, 2018
7825296
Minor verbiage tweaks
scottaddie Mar 2, 2018
b077c4b
WIP
stevejgordon Mar 20, 2018
44be1a5
Working on Polly sample and documentation
stevejgordon Apr 4, 2018
f95bd56
Using code from sample in docs
stevejgordon Apr 4, 2018
d231feb
UE pass
scottaddie Apr 5, 2018
957f760
Convert usage H2 headings to H3
scottaddie Apr 5, 2018
f715142
Adding initial logging information
stevejgordon Apr 6, 2018
05e139f
Verbiage tweaks
scottaddie Apr 10, 2018
af9c32f
Updating to 2.1 preview 2
stevejgordon Apr 16, 2018
aaf3240
Removing HTTPS redirection since launchSettings does not default to c…
stevejgordon Apr 17, 2018
fdf6d7c
Add monikerRange metadata for 2.1+
scottaddie Apr 23, 2018
c7d9e6d
Major sample and doc content update
stevejgordon Apr 26, 2018
b2c7d60
Adding section about configuring HttpMessageHandler
stevejgordon Apr 27, 2018
699e07d
Updating with feedback from Ryan
stevejgordon Apr 27, 2018
e4bd7f0
Feedback and updates
stevejgordon Apr 28, 2018
d7a5b8c
Incorporate Acrolinx feedback
scottaddie Apr 30, 2018
4c76827
Updating sample with preferred idioms and minor doc tweaks
stevejgordon May 2, 2018
8a37fc7
Fixing grammar and spelling
stevejgordon May 2, 2018
b34cda6
Add 2.1 Preview include
scottaddie May 2, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 244 additions & 0 deletions aspnetcore/fundamentals/http-requests.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;

namespace HttpClientFactorySample.Controllers
{
public class ThirdPartyController : Controller
{
[Route("unreliable")]
public IActionResult UnreliableEndpoint()
{
var second = DateTime.UtcNow.Second;

// about 50% of the time this will fail
return second % 2 != 0 ? Ok() : StatusCode(HttpStatusCode.ServiceUnavailable);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Threading.Tasks;
using HttpClientFactorySample.Services;
using Microsoft.AspNetCore.Mvc;

namespace HttpClientFactorySample.Controllers
{
public class UnreliableConsumerController : Controller
{
private readonly UnreliableEndpointCallerService _unreliableEndpointCallerService;

public UnreliableConsumerController(UnreliableEndpointCallerService unreliableEndpointCallerService)
{
_unreliableEndpointCallerService = unreliableEndpointCallerService;
}

[Route("unreliable-consumer")]
public async Task<IActionResult> UnreliableEndpointConsumer()
{
// Builds a URI to what we will imagine is an external endpoint that is unreliable. For this sample we are hosting our own unreliable endpoint to demonstrate!

var url = Url.Action("UnreliableEndpoint", "ThirdParty");

var uriBuilder = new UriBuilder
{
Scheme = HttpContext.Request.Scheme,
Host = HttpContext.Request.Host.Host,
Port = HttpContext.Request.Host.Port ?? 80,
Path = url
};

// call the typed client that has been registered in ConfigureServices

var status = await _unreliableEndpointCallerService.GetDataFromUnreliableEndpoint(uriBuilder.Uri.ToString());

return Ok(status);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace HttpClientFactorySample.GitHub
{
/// <summary>
/// A partial representation of a branch object from the GitHub API
/// </summary>
public class GitHubBranch
{
public string Name { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using Newtonsoft.Json;

namespace HttpClientFactorySample.GitHub
{
/// <summary>
/// A partial representation of an issue object from the GitHub API
/// </summary>
public class GitHubIssue
{
[JsonProperty(PropertyName = "html_url")]
public string Url { get; set; }

public string Title { get; set; }

[JsonProperty(PropertyName = "created_at")]
public DateTime Created { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace HttpClientFactorySample.GitHub
{
/// <summary>
/// A partial representation of a pull request object from the GitHub API
/// </summary>
public class GitHubPullRequest
{
public string Title { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;

namespace HttpClientFactorySample.GitHub
{
/// <summary>
/// Exposes methods to return GitHub API data
/// </summary>
#region snippet1
public class GitHubService
{
public HttpClient Client { get; }

public GitHubService(HttpClient client)
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); // GitHub API versioning
client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); // GitHub requires a user-agent

Client = client;
}

public async Task<IEnumerable<GitHubIssue>> GetAspNetDocsIssues()
{
var response = await Client.GetAsync("/repos/aspnet/docs/issues?state=open&sort=created&direction=desc");

response.EnsureSuccessStatusCode();

var result = await response.Content.ReadAsAsync<IEnumerable<GitHubIssue>>();

return result;
}
}
#endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;

namespace HttpClientFactorySample.GitHub
{
#region snippet1
public class RepoService
{
private readonly HttpClient _httpClient; // not exposed publically

public RepoService(HttpClient client)
{
_httpClient = client;
}

public async Task<IEnumerable<string>> GetRepos()
{
var response = await _httpClient.GetAsync("aspnet/repos");

response.EnsureSuccessStatusCode();

var result = await response.Content.ReadAsAsync<IEnumerable<string>>();

return result;
}
}
#endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace HttpClientFactorySample.Handlers
{
#region snippet1
public class RequestDataHandler : DelegatingHandler
{
private readonly ILogger<RequestDataHandler> _logger;

private const string RequestSourceHeaderName = "Request-Source";
private const string RequestSource = "HttpClientFactorySampleApp";
private const string RequestIdHeaderName = "Request-Identifier";

public RequestDataHandler(ILogger<RequestDataHandler> logger)
{
_logger = logger;
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
var identifier = Guid.NewGuid(); // some information we want to generate and add per request

_logger.LogInformation($"Starting request {identifier}");

request.Headers.Add(RequestSourceHeaderName, RequestSource);
request.Headers.Add(RequestIdHeaderName, identifier.ToString());

return base.SendAsync(request, cancellationToken);
}
}
#endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace HttpClientFactorySample.Handlers
{
public class SecureRequestHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.RequestUri.Scheme == Uri.UriSchemeHttp)
{
var builder = new UriBuilder(request.RequestUri) { Scheme = Uri.UriSchemeHttps };
request.RequestUri = builder.Uri;
}

return base.SendAsync(request, cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace HttpClientFactorySample.Handlers
{
#region snippet1
public class ValidateHeaderHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (!request.Headers.Contains("X-API-KEY"))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("You must supply an API key header called X-API-KEY")
};
}

return await base.SendAsync(request, cancellationToken);
}
}
#endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.1.0-preview2-final" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.0-preview2-final" />
</ItemGroup>

<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.1.0-preview1-final" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@page
@model BasicUsageModel
@{
ViewData["Title"] = "Branches for Docs Repo";
}

<h1>@ViewData["Title"]</h1>

@if (Model.GetBranchesError)
{
<p>Unable to get branches from GitHub. Please try again later.</p>
}
else
{
<ul>
@foreach (var branch in Model.Branches)
{
<li>@branch.Name</li>
}
</ul>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using HttpClientFactorySample.GitHub;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace HttpClientFactorySample.Pages
{
#region snippet1
public class BasicUsageModel : PageModel
{
private readonly IHttpClientFactory _clientFactory;

public IEnumerable<GitHubBranch> Branches { get; private set; }

public bool GetBranchesError { get; private set; }

public BasicUsageModel(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}

public async Task OnGet()
{
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/aspnet/docs/branches");
request.Headers.Add("Accept", "application/vnd.github.v3+json");
request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

var client = _clientFactory.CreateClient();

var response = await client.SendAsync(request);

if (response.IsSuccessStatusCode)
{
Branches = await response.Content.ReadAsAsync<IEnumerable<GitHubBranch>>();
}
else
{
GetBranchesError = true;
Branches = Array.Empty<GitHubBranch>();
}
}
}
#endregion
}
23 changes: 23 additions & 0 deletions aspnetcore/fundamentals/http-requests/samples/Pages/Error.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}

<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
</p>
Loading