Skip to content

Commit d9f1a5a

Browse files
committed
Blazor call web API topic with sample
Updates
1 parent 0018bbf commit d9f1a5a

File tree

7 files changed

+583
-0
lines changed

7 files changed

+583
-0
lines changed

aspnetcore/blazor/call-web-api.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
---
2+
title: Call a web API
3+
author: guardrex
4+
description: Learn how to call a web API from a Blazor app using JSON helpers, including making cross-origin resource sharing (CORS) requests.
5+
monikerRange: '>= aspnetcore-3.0'
6+
ms.author: riande
7+
ms.custom: mvc
8+
ms.date: 05/20/2019
9+
uid: blazor/call-web-api
10+
---
11+
# Call a web API
12+
13+
By [Luke Latham](https://github.com/guardrex)
14+
15+
Blazor apps call web API services using [HttpClient](xref:fundamentals/http-requests). Compose requests using Blazor JSON helpers or with <xref:System.Net.Http.HttpRequestMessage>, which can include JavaScript [Fetch API](https://developer.mozilla.org/docs/Web/API/Fetch_API) request options.
16+
17+
[View or download sample code](https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/blazor/common/samples/) ([how to download](xref:index#how-to-download-a-sample))
18+
19+
See the following components in the sample app:
20+
21+
* Call Web API (*Pages/CallWebAPI.razor*)
22+
* HTTP Request Tester (*Components/HTTPRequestTester.razor*)
23+
24+
## HttpClient and JSON helpers
25+
26+
Use [HttpClient](xref:fundamentals/http-requests) and JSON helpers to call a web API service endpoint in a Razor component. Blazor client-side uses the [Fetch API](https://developer.mozilla.org/docs/Web/API/Fetch_API), while Blazor server-side uses <xref:System.Net.Http.HttpClient?displayProperty=fullName>.
27+
28+
Include an `@using` statement for <xref:System.Threading.Tasks> for asynchronous web API calls and inject an `HttpClient` instance:
29+
30+
```cshtml
31+
@using System.Threading.Tasks
32+
@inject HttpClient Http
33+
```
34+
35+
In the following examples, a Todo web API service processes create, read, update, and delete (CRUD) operations. The examples are based on a `TodoItem` class that stores the:
36+
37+
* ID (`Id`, `long`) &ndash; Unique ID of the item.
38+
* Name (`Name`, `string`) &ndash; Name of the item.
39+
* Status (`IsComplete`, `bool`) &ndash; Indication if the Todo item is finished.
40+
41+
```csharp
42+
private class TodoItem
43+
{
44+
public long Id { get; set; }
45+
public string Name { get; set; }
46+
public bool IsComplete { get; set; }
47+
}
48+
```
49+
50+
JSON helper methods send requests to a URI (a web API in the following examples) and process the response:
51+
52+
* `GetJsonAsync` &ndash; Sends a GET request and parses the JSON response body to create an object.
53+
54+
In the following code, the `_todoItems` are displayed by the component. The `GetTodoItems` method is triggered when the component is finished rendering ([OnInitAsync](xref:blazor/components#lifecycle-methods)). See the sample app for a complete example.
55+
56+
```cshtml
57+
@using Microsoft.AspNetCore.Blazor.Http
58+
@inject HttpClient Http
59+
60+
@functions {
61+
private const string ServiceEndpoint = "https://localhost:10000/api/todo";
62+
private TodoItem[] _todoItems;
63+
64+
protected override async Task OnInitAsync() =>
65+
await GetTodoItems();
66+
67+
private async Task GetTodoItems() =>
68+
_todoItems = await Http.GetJsonAsync<TodoItem[]>(ServiceEndpoint);
69+
}
70+
```
71+
72+
* `PostJsonAsync` &ndash; Sends a POST request, including JSON-encoded content, and parses the JSON response body to create an object.
73+
74+
In the following code, `_newItemName` is provided by a bound element of the component. The `AddItem` method is triggered by selecting a `<button>` element. See the sample app for a complete example.
75+
76+
```cshtml
77+
@using Microsoft.AspNetCore.Blazor.Http
78+
@inject HttpClient Http
79+
80+
<input type="text" bind="@_newItemName" placeholder="New Todo Item" />
81+
<button onclick="@(async () => await AddItem())">Add</button>
82+
83+
@functions {
84+
private const string ServiceEndpoint = "https://localhost:10000/api/todo";
85+
private string _newItemName;
86+
87+
private async Task AddItem()
88+
{
89+
var addItem = new TodoItem { Name = _newItemName, IsComplete = false };
90+
await Http.PostJsonAsync(ServiceEndpoint, addItem);
91+
}
92+
}
93+
```
94+
95+
* `PutJsonAsync` &ndash; Sends a PUT request, including JSON-encoded content.
96+
97+
In the following code, `_editItem` values (`Id`, `Name`, `IsCompleted`) are provided by bound elements of the component. The `SaveItem` method is triggered by selecting the Save `<button>` element. See the sample app for a complete example.
98+
99+
```cshtml
100+
@using Microsoft.AspNetCore.Blazor.Http
101+
@inject HttpClient Http
102+
103+
<input type="text" bind="@_editItem.Id" />
104+
<input type="checkbox" bind="@_editItem.IsComplete" />
105+
<input type="text" bind="@_editItem.Name" />
106+
<button onclick="@(async () => await SaveItem())">Save</button>
107+
108+
@functions {
109+
private const string ServiceEndpoint = "https://localhost:10000/api/todo";
110+
private TodoItem _editItem = new TodoItem();
111+
112+
private async Task SaveItem()
113+
{
114+
await Http.PutJsonAsync(
115+
Path.Combine(ServiceEndpoint, _editItem.Id.ToString()), _editItem);
116+
}
117+
}
118+
```
119+
120+
<xref:System.Net.Http> includes additional extension methods for sending HTTP requests and receiving HTTP responses. [HttpClient.DeleteAsync](xref:System.Net.Http.HttpClient.DeleteAsync*) is used to send a DELETE request to a web API.
121+
122+
In the following code, the Delete `<button>` element supplies the `id` when it's selected in the UI. See the sample app for a complete example.
123+
124+
```cshtml
125+
@using Microsoft.AspNetCore.Blazor.Http
126+
@inject HttpClient Http
127+
128+
<input type="text" bind="@_id" />
129+
<button onclick="@(async () => await DeleteItem())">Delete</button>
130+
131+
@functions {
132+
private const string ServiceEndpoint = "https://localhost:10000/api/todo";
133+
private long _id;
134+
135+
private async Task DeleteItem()
136+
{
137+
await Http.DeleteAsync(Path.Combine(ServiceEndpoint, _id.ToString()));
138+
}
139+
}
140+
```
141+
142+
## HttpClient and HttpRequestMessage with Fetch API request options
143+
144+
Use [HttpClient](xref:fundamentals/http-requests) and <xref:System.Net.Http.HttpRequestMessage> to supply request options to the underlying JavaScript [Fetch API](https://developer.mozilla.org/docs/Web/API/Fetch_API).
145+
146+
In the following example:
147+
148+
* JSON serialization and deserialization must be handled by user code (*not shown*).
149+
* The `credentials` property is set to any of the following values:
150+
151+
* `FetchCredentialsOption.Include` ("include") &ndash; Advises the browser to send credentials (such as cookies or HTTP auth headers) even for cross-origin requests. Only allowed when the CORS Middleware policy in the web API is configured to <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.AllowCredentials*>.
152+
* `FetchCredentialsOption.Omit` ("omit") &ndash; Advises the browser never to send credentials (such as cookies or HTTP auth headers).
153+
* `FetchCredentialsOption.SameOrigin` ("same-origin") &ndash; Advises the browser to send credentials (such as cookies or HTTP auth headers) only if the target URL is on the same origin as the calling application.
154+
155+
```cshtml
156+
@using System.Net.Http.Headers
157+
@using Microsoft.AspNetCore.Blazor.Http
158+
@inject HttpClient Http
159+
160+
@functions {
161+
private async Task PostRequest()
162+
{
163+
Http.DefaultRequestHeaders.Authorization =
164+
new AuthenticationHeaderValue("Bearer", "{OAUTH TOKEN}");
165+
166+
var requestMessage = new HttpRequestMessage()
167+
{
168+
Method = new HttpMethod("POST"),
169+
RequestUri = new Uri("https://localhost:10000/api/todo"),
170+
Content =
171+
new StringContent(
172+
@"{""name"":""A New Todo Item"",""isComplete"":false}")
173+
};
174+
175+
requestMessage.Content.Headers.ContentType =
176+
new System.Net.Http.Headers.MediaTypeHeaderValue(
177+
"application/json");
178+
179+
requestMessage.Content.Headers.TryAddWithoutValidation(
180+
"x-custom-header", "value");
181+
182+
requestMessage.Properties[WebAssemblyHttpMessageHandler.FetchArgs] = new
183+
{
184+
credentials = FetchCredentialsOption.Include
185+
};
186+
187+
var response = await Http.SendAsync(requestMessage);
188+
var responseStatusCode = response.StatusCode;
189+
var responseBody = await response.Content.ReadAsStringAsync();
190+
}
191+
}
192+
```
193+
194+
For more information on Fetch API options, see [MDN web docs: Window​OrWorker​Global​Scope​.fetch():Parameters](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters).
195+
196+
When sending credentials (authorization cookies/headers) on CORS requests, allow the `Authorization` header when creating the CORS policy for CORS middleware. The following policy includes configuration for:
197+
198+
* Request origins (`http://localhost:5000`, `https://localhost:5001`).
199+
* Any method (verb).
200+
* `Content-Type` and `Authorization` headers. To allow a custom header (for example, `x-custom-header`), list the header when calling <xref:Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder.WithHeaders*>.
201+
* Credentials set by client-side JavaScript code (`credentials` property set to `include`).
202+
203+
```csharp
204+
app.UseCors(policy =>
205+
policy.WithOrigins("http://localhost:5000", "https://localhost:5001")
206+
.AllowAnyMethod()
207+
.WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization, "x-custom-header")
208+
.AllowCredentials());
209+
```
210+
211+
For more information, see <xref:security/cors> and the sample app's HTTP Request Tester component (*Components/HTTPRequestTester.razor*).
212+
213+
## Cross-origin resource sharing (CORS)
214+
215+
For more information on making cross-origin resource sharing (CORS) requests, see <xref:security/cors>. The sample app demonstrates CORS. See the Call Web API component (*Pages/CallWebAPI.razor*).
216+
217+
## HTTP Request Tester
218+
219+
The sample app includes an HTTP Request Tester component (*Components/HTTPRequestTester.razor*). The component is included in the Call Web API component:
220+
221+
```cshtml
222+
<HTTPRequestTester />
223+
```
224+
225+
Use the component to test request-responses against web API service endpoints.
226+
227+
## Additional resources
228+
229+
* <xref:fundamentals/http-requests>
230+
* [Cross Origin Resource Sharing (CORS) at W3C](https://www.w3.org/TR/cors/)

0 commit comments

Comments
 (0)