mirror of
https://github.com/m-lamonaca/dev-notes.git
synced 2025-06-08 18:57:12 +00:00
show line numbers in conde snippets
This commit is contained in:
parent
cd1df0e376
commit
255a68d673
82 changed files with 1249 additions and 1251 deletions
|
@ -18,7 +18,7 @@ The component class is usually written in the form of a Razor markup page with a
|
|||
|
||||
[Blazor Components](https://docs.microsoft.com/en-us/aspnet/core/blazor/components/)
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
@page "/route/{RouteParameter}" // make component accessible from a URL
|
||||
@page "/route/{RouteParameter?}" // specify route parameter as optional
|
||||
@page "/route/{RouteParameter:<type>}" // specify route parameter type
|
||||
|
@ -59,7 +59,7 @@ The component class is usually written in the form of a Razor markup page with a
|
|||
|
||||
It's now possible to pass state when navigating in Blazor apps using the `NavigationManager`.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
navigationManager.NavigateTo("/<route>", new NavigationOptions { HistoryEntryState = value });
|
||||
```
|
||||
|
||||
|
@ -67,12 +67,12 @@ This mechanism allows for simple communication between different pages. The spec
|
|||
|
||||
### Blazor WASM
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// setup state singleton
|
||||
builder.Services.AddSingleton<StateContainer>();
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// StateContainer singleton
|
||||
using System;
|
||||
|
||||
|
@ -96,7 +96,7 @@ public class StateContainer
|
|||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// component that changes the state
|
||||
@inject StateContainer State
|
||||
|
||||
|
@ -113,7 +113,7 @@ public class StateContainer
|
|||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// component that should be update on state change
|
||||
@implements IDisposable
|
||||
@inject StateContainer State
|
||||
|
@ -139,7 +139,7 @@ public class StateContainer
|
|||
|
||||
## Data Binding & Events
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
<p>
|
||||
<button @on{DOM EVENT}="{DELEGATE}" />
|
||||
<button @on{DOM EVENT}="{DELEGATE}" @on{DOM EVENT}:preventDefault /> // prevent default action
|
||||
|
@ -186,7 +186,6 @@ public class StateContainer
|
|||
```
|
||||
|
||||
> **Note**: When a user provides an unparsable value to a data-bound element, the unparsable value is automatically reverted to its previous value when the bind event is triggered.
|
||||
|
||||
> **Note**: The `@bind:get` and `@bind:set` modifiers are always used together.
|
||||
> `The @bind:get` modifier specifies the value to bind to and the `@bind:set` modifier specifies a callback that is called when the value changes
|
||||
|
||||
|
@ -199,7 +198,7 @@ public class StateContainer
|
|||
|
||||
To render a Blazor component from JavaScript, first register it as a root component for JavaScript rendering and assign it an identifier:
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// Blazor Server
|
||||
builder.Services.AddServerSideBlazor(options =>
|
||||
{
|
||||
|
@ -212,7 +211,7 @@ builder.RootComponents.RegisterForJavaScript<Counter>(identifier: "counter");
|
|||
|
||||
Load Blazor into the JavaScript app (`blazor.server.js` or `blazor.webassembly.js`) and then render the component from JavaScript into a container element using the registered identifier, passing component parameters as needed:
|
||||
|
||||
```js
|
||||
```js linenums="1"
|
||||
let containerElement = document.getElementById('my-counter');
|
||||
await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });
|
||||
```
|
||||
|
@ -224,6 +223,6 @@ Custom elements use standard HTML interfaces to implement custom HTML elements.
|
|||
|
||||
To create a custom element using Blazor, register a Blazor root component as custom elements like this:
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
options.RootComponents.RegisterAsCustomElement<Counter>("my-counter");
|
||||
```
|
||||
|
|
|
@ -85,7 +85,7 @@ Filter attributes:
|
|||
|
||||
## **Filter scopes**
|
||||
|
||||
A filter can be added to the pipeline at one of three *scopes*:
|
||||
A filter can be added to the pipeline at one of three _scopes_:
|
||||
|
||||
- Using an attribute on a controller action. Filter attributes cannot be applied to Razor Pages handler methods.
|
||||
|
||||
|
@ -124,14 +124,14 @@ builder.Services.AddControllersWithViews(options =>
|
|||
|
||||
When there are multiple filters for a particular stage of the pipeline, scope determines the default order of filter execution. Global filters surround class filters, which in turn surround method filters.
|
||||
|
||||
As a result of filter nesting, the *after* code of filters runs in the reverse order of the *before* code. The filter sequence:
|
||||
As a result of filter nesting, the _after_ code of filters runs in the reverse order of the _before_ code. The filter sequence:
|
||||
|
||||
- The *before* code of global filters.
|
||||
- The *before* code of controller and Razor Page filters.
|
||||
- The *before* code of action method filters.
|
||||
- The *after* code of action method filters.
|
||||
- The *after* code of controller and Razor Page filters.
|
||||
- The *after* code of global filters.
|
||||
- The _before_ code of global filters.
|
||||
- The _before_ code of controller and Razor Page filters.
|
||||
- The _before_ code of action method filters.
|
||||
- The _after_ code of action method filters.
|
||||
- The _after_ code of controller and Razor Page filters.
|
||||
- The _after_ code of global filters.
|
||||
|
||||
### Cancellation and Short-Circuiting
|
||||
|
||||
|
@ -156,7 +156,7 @@ public class ShortCircuitingResourceFilterAttribute : Attribute, IResourceFilter
|
|||
|
||||
## Dependency Injection
|
||||
|
||||
Filters can be added _by type_ or _by instance_. If an instance is added, that instance is used for every request. If a type is added, it's type-activated.
|
||||
Filters can be added _by type_ or _by instance_. If an instance is added, that instance is used for every request. If a type is added, it's type-activated.
|
||||
|
||||
A type-activated filter means:
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ Short-circuiting is often desirable because it avoids unnecessary work.
|
|||
|
||||
It's possible to perform actions both *before* and *after* the next delegate:
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// "inline" middleware, best if in own class
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ app.Use(async (context, next) =>
|
|||
|
||||
`Run` delegates don't receive a next parameter. The first `Run` delegate is always terminal and terminates the pipeline.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// "inline" middleware, best if in own class
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ The Endpoint middleware executes the filter pipeline for the corresponding app t
|
|||
|
||||
The order that middleware components are added in the `Startup.Configure` method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is **critical** for security, performance, and functionality.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
@ -121,7 +121,7 @@ Unlike with `MapWhen`, this branch is rejoined to the main pipeline if it doesn'
|
|||
|
||||
Middleware is generally encapsulated in a class and exposed with an extension method.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public class CustomMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
@ -152,7 +152,7 @@ The middleware class **must** include:
|
|||
|
||||
## Middleware Extension Methods
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
public static class MiddlewareExtensions
|
||||
|
@ -164,7 +164,7 @@ public static class MiddlewareExtensions
|
|||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// other middlewares
|
||||
|
||||
app.UseCustom(); // add custom middleware in the pipeline
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> **Note**: Requires .NET 6+
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddSingleton<IService, Service>();
|
||||
|
@ -18,7 +18,6 @@ app.Run();
|
|||
app.RunAsync();
|
||||
```
|
||||
|
||||
|
||||
## Application Settings
|
||||
|
||||
App settings are loaded (in order) from:
|
||||
|
@ -42,7 +41,7 @@ Setting a value is done with `dotnet user-secrets set <key> <value>`, keys can b
|
|||
|
||||
## Swagger
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
|
@ -60,7 +59,7 @@ app.MapPost("/route", Handler).Accepts<Type>(contentType);
|
|||
|
||||
## MVC
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
builder.Services.AddControllersWithViews();
|
||||
//or
|
||||
builder.Services.AddControllers();
|
||||
|
@ -96,7 +95,7 @@ app.MapControllerRoute(
|
|||
|
||||
To define routes and handlers using Minimal APIs, use the `Map(Get|Post|Put|Delete)` methods.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// the dependencies are passed as parameters in the handler delegate
|
||||
app.MapGet("/route/{id}", (IService service, int id) => {
|
||||
|
||||
|
@ -113,7 +112,7 @@ IResult Search(int id, int? page = 1, int? pageSize = 10) { /* ... */ }
|
|||
The `MapGroup()` extension method, which helps organize groups of endpoints with a common prefix.
|
||||
It allows for customizing entire groups of endpoints with a singe call to methods like `RequireAuthorization()` and `WithMetadata()`.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
var group = app.MapGroup("<route-prefix>");
|
||||
|
||||
group.MapGet("/", GetAllTodos); // route: /<route-prefix>
|
||||
|
@ -127,14 +126,14 @@ group.MapGet("/{id}", GetTodo); // route: /<route-prefix>/{id}
|
|||
The `Microsoft.AspNetCore.Http.TypedResults` static class is the “typed” equivalent of the existing `Microsoft.AspNetCore.Http.Results` class.
|
||||
It's possible to use `TypedResults` in minimal APIs to create instances of the in-framework `IResult`-implementing types and preserve the concrete type information.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public static async Task<IResult> GetAllTodos(TodoDb db)
|
||||
{
|
||||
return TypedResults.Ok(await db.Todos.ToArrayAsync());
|
||||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
[Fact]
|
||||
public async Task GetAllTodos_ReturnsOkOfObjectResult()
|
||||
{
|
||||
|
@ -153,7 +152,7 @@ public async Task GetAllTodos_ReturnsOkOfObjectResult()
|
|||
|
||||
The `Results<TResult1, TResult2, TResultN>` generic union types, along with the `TypesResults` class, can be used to declare that a route handler returns multiple `IResult`-implementing concrete types.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// Declare that the lambda returns multiple IResult types
|
||||
app.MapGet("/todos/{id}", async Results<Ok<Todo>, NotFound> (int id, TodoDb db)
|
||||
{
|
||||
|
@ -165,7 +164,7 @@ app.MapGet("/todos/{id}", async Results<Ok<Todo>, NotFound> (int id, TodoDb db)
|
|||
|
||||
## Filters
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public class ExampleFilter : IRouteHandlerFilter
|
||||
{
|
||||
public async ValueTask<object?> InvokeAsync(RouteHandlerInvocationContext context, RouteHandlerFilterDelegate next)
|
||||
|
@ -178,7 +177,7 @@ public class ExampleFilter : IRouteHandlerFilter
|
|||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
app.MapPost("/route", Handler).AddFilter<ExampleFilter>();
|
||||
```
|
||||
|
||||
|
@ -192,7 +191,7 @@ With Minimal APIs it's possible to access the contextual information by passing
|
|||
- `ClaimsPrincipal`
|
||||
- `CancellationToken` (RequestAborted)
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
app.MapGet("/hello", (ClaimsPrincipal user) => {
|
||||
return "Hello " + user.FindFirstValue("sub");
|
||||
});
|
||||
|
@ -202,7 +201,7 @@ app.MapGet("/hello", (ClaimsPrincipal user) => {
|
|||
|
||||
The `Microsoft.AspNetCore.OpenApi` package exposes a `WithOpenApi` extension method that generates an `OpenApiOperation` derived from a given endpoint’s route handler and metadata.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
app.MapGet("/todos/{id}", (int id) => ...)
|
||||
.WithOpenApi();
|
||||
|
||||
|
@ -218,7 +217,7 @@ app.MapGet("/todos/{id}", (int id) => ...)
|
|||
Using [Minimal Validation](https://github.com/DamianEdwards/MinimalValidation) by Damian Edwards.
|
||||
Alternatively it's possible to use [Fluent Validation](https://fluentvalidation.net/).
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
app.MapPost("/widgets", (Widget widget) => {
|
||||
var isValid = MinimalValidation.TryValidate(widget, out var errors);
|
||||
|
||||
|
@ -241,7 +240,7 @@ class Widget
|
|||
|
||||
## JSON Serialization
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// Microsoft.AspNetCore.Http.Json.JsonOptions
|
||||
builder.Services.Configure<JsonOptions>(opt =>
|
||||
{
|
||||
|
@ -251,7 +250,7 @@ builder.Services.Configure<JsonOptions>(opt =>
|
|||
|
||||
## Authorization
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer();
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
|
@ -284,13 +283,13 @@ app.MapGet("/special-secret", () => "This is a special secret!")
|
|||
The `user-jwts` tool is similar in concept to the existing `user-secrets` tools, in that it can be used to manage values for the app that are only valid for the current user (the developer) on the current machine.
|
||||
In fact, the `user-jwts` tool utilizes the `user-secrets` infrastructure to manage the key that the JWTs will be signed with, ensuring it’s stored safely in the user profile.
|
||||
|
||||
```sh
|
||||
```sh linenums="1"
|
||||
dotnet user-jwts create # configure a dev JWT fot the current user
|
||||
```
|
||||
|
||||
## Output Caching
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
builder.Services.AddOutputCaching(); // no special options
|
||||
builder.Services.AddOutputCaching(options =>
|
||||
{
|
||||
|
@ -322,7 +321,7 @@ app.MapGet("/<route>", [OutputCache(/* options */)]RouteHandler);
|
|||
|
||||
### Cache Eviction
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
|
||||
app.MapGet("/<route-one>", RouteHandler).CacheOutput(x => x.Tag("<tag>")); // tag cache portion
|
||||
|
||||
|
@ -334,11 +333,11 @@ app.MapGet("/<route-two>", (IOutputCacheStore cache, CancellationToken token) =>
|
|||
|
||||
### Custom Cache Policy
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
app.MapGet("/<route-one>", RouteHandler).CacheOutput(x => x.AddCachePolicy<CustomCachePolicy>());
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
class CustomCachePolicy : IOutputCachePolicy
|
||||
{
|
||||
public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken) { }
|
||||
|
@ -353,7 +352,7 @@ class CustomCachePolicy : IOutputCachePolicy
|
|||
|
||||
The *options pattern* uses classes to provide strongly-typed access to groups of related settings.
|
||||
|
||||
```json
|
||||
```json linenums="1"
|
||||
{
|
||||
"SecretKey": "Secret key value",
|
||||
"TransientFaultHandlingOptions": {
|
||||
|
@ -370,7 +369,7 @@ The *options pattern* uses classes to provide strongly-typed access to groups of
|
|||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// options model for binding
|
||||
public class TransientFaultHandlingOptions
|
||||
{
|
||||
|
@ -379,13 +378,13 @@ public class TransientFaultHandlingOptions
|
|||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
// setup the options
|
||||
builder.Services.Configure<TransientFaultHandlingOptions>(builder.Configuration.GetSection<TransientFaultHandlingOptions>(nameof(Options)));
|
||||
builder.Services.Configure<TransientFaultHandlingOptions>(builder.Configuration.GetSection<TransientFaultHandlingOptions>(key));
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
class DependsOnOptions
|
||||
{
|
||||
private readonly IOptions<TransientFaultHandlingOptions> _options;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Markup
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
@page // set this as razor page
|
||||
|
||||
@model <App>.Models.Entity // if MVC set type of elements passed to the view
|
||||
|
@ -35,7 +35,7 @@
|
|||
|
||||
Example:
|
||||
|
||||
```html
|
||||
```html linenums="1"
|
||||
<!-- tag helpers for a lin in ASP.NET MVC -->
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
||||
```
|
||||
|
@ -44,7 +44,7 @@ Example:
|
|||
|
||||
The `@addTagHelper` directive makes Tag Helpers available to the view. Generally, the view file is `Pages/_ViewImports.cshtml`, which by default is inherited by all files in the `Pages` folder and subfolders, making Tag Helpers available.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
@using <App>
|
||||
@namespace <App>.Pages // or <Project>.Models
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
@ -57,7 +57,7 @@ The first parameter after `@addTagHelper` specifies the Tag Helpers to load (`*`
|
|||
|
||||
It's possible to disable a Tag Helper at the element level with the Tag Helper opt-out character (`!`)
|
||||
|
||||
```cshtml
|
||||
```cshtml linenums="1"
|
||||
<!-- disable email validation -->
|
||||
<!span asp-validation-for="Email" ></!span>
|
||||
```
|
||||
|
@ -66,7 +66,7 @@ It's possible to disable a Tag Helper at the element level with the Tag Helper o
|
|||
|
||||
The `@tagHelperPrefix` directive allows to specify a tag prefix string to enable Tag Helper support and to make Tag Helper usage explicit.
|
||||
|
||||
```cshtml
|
||||
```cshtml linenums="1"
|
||||
@tagHelpersPrefix th:
|
||||
```
|
||||
|
||||
|
@ -74,7 +74,7 @@ The `@tagHelperPrefix` directive allows to specify a tag prefix string to enable
|
|||
|
||||
[Understanding Html Helpers](https://stephenwalther.com/archive/2009/03/03/chapter-6-understanding-html-helpers)
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
@model <App>.Models.Entity
|
||||
|
||||
// Display the name of the property
|
||||
|
@ -112,7 +112,7 @@ The `@tagHelperPrefix` directive allows to specify a tag prefix string to enable
|
|||
|
||||
In `ViewModel.cs`:
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
class ViewModel
|
||||
{
|
||||
public int EntityId { get; set; } // value selected in form ends up here
|
||||
|
@ -126,7 +126,7 @@ class ViewModel
|
|||
|
||||
In `View.cs`
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
@model ViewModel
|
||||
|
||||
<form asp-controller="Controller" asp-action="PostAction">
|
||||
|
@ -140,7 +140,7 @@ In `View.cs`
|
|||
|
||||
In `Controller.cs`:
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public IActionResult GetAction()
|
||||
{
|
||||
var vm = new ViewModel();
|
||||
|
|
|
@ -8,7 +8,7 @@ The SignalR Hubs API enables to call methods on connected clients from the serve
|
|||
|
||||
In `Startup.cs`:
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
var app = builder.Build();
|
||||
|
@ -21,7 +21,7 @@ app.UseEndpoints(endpoints =>
|
|||
|
||||
### Creating Hubs
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public class CustomHub : Hub
|
||||
{
|
||||
public task HubMethod(Type args)
|
||||
|
@ -46,7 +46,7 @@ A drawback of using `SendAsync` is that it relies on a magic string to specify t
|
|||
|
||||
An alternative to using SendAsync is to strongly type the Hub with `Hub<T>`.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public interface IHubClient
|
||||
{
|
||||
// matches method to be called on the client
|
||||
|
@ -54,7 +54,7 @@ public interface IHubClient
|
|||
}
|
||||
```
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public class CustomHub : Hub<IHubClient>
|
||||
{
|
||||
public Task HubMethod(Type args)
|
||||
|
@ -72,7 +72,7 @@ Using a strongly typed `Hub<T>` disables the ability to use `SendAsync`. Any met
|
|||
|
||||
The SignalR Hubs API provides the OnConnectedAsync and OnDisconnectedAsync virtual methods to manage and track connections. Override the OnConnectedAsync virtual method to perform actions when a client connects to the Hub, such as adding it to a group.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public override async Task OnConnectedAsync()
|
||||
{
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, "GroupName");
|
||||
|
@ -98,7 +98,7 @@ If the Hub throws an exception, connections aren't closed. By default, SignalR r
|
|||
|
||||
If you have an exceptional condition you *do* want to propagate to the client, use the `HubException` class. If you throw a `HubException` from your hub method, SignalR will send the entire message to the client, unmodified.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public Task ThrowException()
|
||||
{
|
||||
throw new HubException("This error will be sent to the client!");
|
||||
|
@ -109,7 +109,7 @@ public Task ThrowException()
|
|||
|
||||
### Installing the client package
|
||||
|
||||
```sh
|
||||
```sh linenums="1"
|
||||
npm init -y
|
||||
npm install @microsoft/signalr
|
||||
```
|
||||
|
@ -118,7 +118,7 @@ npm installs the package contents in the `node_modules\@microsoft\signalr\dist\b
|
|||
|
||||
Reference the SignalR JavaScript client in the `<script>` element. For example:
|
||||
|
||||
```html
|
||||
```html linenums="1"
|
||||
<script src="~/lib/signalr/signalr.js"></script>
|
||||
```
|
||||
|
||||
|
@ -126,7 +126,7 @@ Reference the SignalR JavaScript client in the `<script>` element. For example:
|
|||
|
||||
[Reconnect Clients Docs](https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client#reconnect-clients)
|
||||
|
||||
```js
|
||||
```js linenums="1"
|
||||
const connection = new signalR.HubConnectionBuilder()
|
||||
.withUrl("/hub/endpoint")
|
||||
.configureLogging(signalR.LogLevel.Information)
|
||||
|
@ -158,7 +158,7 @@ JavaScript clients call public methods on hubs via the `invoke` method of the `H
|
|||
- The name of the hub method.
|
||||
- Any arguments defined in the hub method.
|
||||
|
||||
```js
|
||||
```js linenums="1"
|
||||
try {
|
||||
await connection.invoke("HubMethod", args);
|
||||
} catch (err) {
|
||||
|
@ -177,6 +177,6 @@ To receive messages from the hub, define a method using the `on` method of the `
|
|||
- The name of the JavaScript client method.
|
||||
- Arguments the hub passes to the method.
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
connection.on("ClientMethod", (args) => { /* ... */});
|
||||
```
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
The fist loaded page is `Default.aspx` and its underlying code.
|
||||
|
||||
```html
|
||||
```html linenums="1"
|
||||
<!-- directive -->
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Project.Default" %>
|
||||
|
||||
|
@ -26,7 +26,7 @@ The fist loaded page is `Default.aspx` and its underlying code.
|
|||
|
||||
### Page Directive
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
<%@ Page Language="C#" // define language used (can be C# or VB)
|
||||
AutoEventWireup="true" // automatically create and setup event handlers
|
||||
CodeBehind="Default.aspx.cs" // define the underlying code file
|
||||
|
@ -35,7 +35,7 @@ The fist loaded page is `Default.aspx` and its underlying code.
|
|||
|
||||
### Web Controls
|
||||
|
||||
```xml
|
||||
```xml linenums="1"
|
||||
<asp:Control ID="" runat="server" ...></asp:Control>
|
||||
|
||||
<!-- Label: empty text will diplay ID, use empty space as text for empty label -->
|
||||
|
@ -59,7 +59,7 @@ The fist loaded page is `Default.aspx` and its underlying code.
|
|||
|
||||
## `Page.aspx.cs`
|
||||
|
||||
```cs
|
||||
```cs linenums="1"
|
||||
public partial class Default : System.Web.UI.Page
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue