.NET

.NET

The .NET framework is a software framework designed mainly for the Microsoft Windows operating system. It includes an implementation of the Base Class Library, Common Language Runtime, Common Type System and Dynamic Language Runtime.
Best of Crypto

Best of Crypto

1656614160

Binance Public API Connector in DotNET

This is a lightweight library that works as a connector to Binance public API

  • Supported APIs:
    • /api/*
    • /sapi/*
    • Spot Websocket Market Stream
    • Spot User Data Stream
  • Test cases and examples
  • Customizable base URL, request timeout and HTTP proxy
  • Response Metadata

Installation

dotnet add package Binance.Spot

RESTful APIs

Usage example

using System;
using System.Threading.Tasks;
using Binance.Spot;

class Program
{
    static async Task Main(string[] args)
    {
        Wallet wallet = new Wallet();

        string status = await wallet.SystemStatus();

        Console.WriteLine(status);
    }
}

Please find more examples folder to check for more endpoints.

Websocket

using System;
using System.Threading;
using System.Threading.Tasks;
using Binance.Spot;

class Program
{
    static async Task Main(string[] args)
    {
        var websocket = new MarketDataWebSocket("btcusdt@aggTrade");

        websocket.OnMessageReceived(
            (data) =>
        {
            Console.WriteLine(data);

            return Task.CompletedTask;
        }, CancellationToken.None);

        await websocket.ConnectAsync(CancellationToken.None);
    }
}

More websocket examples are available in the Examples folder

Heartbeat

Once connected, the websocket server sends a ping frame every 3 minutes and requires a response pong frame back within a 10 minutes period. This package handles the pong responses automatically.

Testnet

While /sapi/* endpoints don't have testnet environment yet, /api/* endpoints can be tested in Spot Testnet.

using Binance.Spot;

Wallet wallet = new Wallet(baseUrl: "https://testnet.binance.vision");

Base URL

If baseUrl is not provided, it defaults to https://api.binance.com.

It's recommended to pass in the baseUrl parameter, even in production as Binance provides alternative URLs in case of performance issues:

  • https://api1.binance.com
  • https://api2.binance.com
  • https://api3.binance.com

RecvWindow parameter

Additional parameter recvWindow is available for endpoints requiring signature.

It defaults to 5000 (milliseconds) and can be any value lower than 60000(milliseconds). Anything beyond the limit will result in an error response from Binance server.

using Binance.Spot;

Wallet wallet = new Wallet();

await wallet.AccountStatus(recvWindow=4000)

Timeout

The default timeout is 100,000 milliseconds (100 seconds).

Usage Example

using System;
using System.Net.Http;
using Binance.Spot;

HttpClient httpClient = new HttpClient() { 
    Timeout = TimeSpan.FromSeconds(10)
}

Wallet wallet = new Wallet(httpClient: httpClient);

Proxy

Usage Example

using System;
using System.Net;
using System.Net.Http;
using Binance.Spot;

WebProxy proxy = new WebProxy(new Uri("http://1.2.3.4:8080"));
HttpClientHandler proxyHandler = new HttpClientHandler { Proxy = proxy };
HttpClient httpClient = new HttpClient(handler: proxyHandler);

Wallet wallet = new Wallet(httpClient: httpClient);

Exceptions

There are 2 types of exceptions returned from the library:

  • Binance.Common.BinanceClientException
    • This is thrown when server returns 4XX, it's an issue from client side.
    • Properties:
      • Code - Server's error code, e.g. -1102
      • Message - Server's error message, e.g. Unknown order sent.
  • Binance.Common.BinanceServerException
    • This is thrown when server returns 5XX, it's an issue from server side.

Both exceptions inherit Binance.Common.BinanceHttpException along with the following properties:

  • StatusCode - Response http status code, e.g. 401
  • Headers - Dictionary with response headers

Logging

This library implements the .NET logging API that works with a variety of built-in and third-party logging providers.

For more information on how to configure logging in .NET, visit Microsoft's logging article

Usage Example

using System;
using System.Net;
using System.Net.Http;
using Binance.Spot;

public async Task LoggingExample(ILogger logger) {
    BinanceLoggingHandler loggingHandler = new BinanceLoggingHandler(logger: logger);
    HttpClient httpClient = new HttpClient(handler: loggingHandler);

    Wallet wallet = new Wallet(httpClient: httpClient);

    await wallet.SystemStatus();
}

Sample Output

Method: GET, RequestUri: 'https://www.binance.com/?timestamp=1631525776809&signature=f07558c98cb82bcb3556a6a21b8a8a2582bae93d0bb9604a0df72cae8c1c6642', Version: 1.1, Content: <null>, Headers: { }
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: <null>, Headers: {}
{"status": 0,"msg": "normal"}

Test Cases

dotnet test

Limitations

Futures and Vanilla Options APIs are not supported:

  • /fapi/*
  • /dapi/*
  • /vapi/*
  • Associated Websocket Market and User Data Streams

Contributing

Contributions are welcome.

If you've found a bug within this project, please open an issue to discuss what you would like to change.

If it's an issue with the API, please open a topic at Binance Developer Community

Download Details:
Author: binance
Source Code: https://github.com/binance/binance-connector-dotnet
License: MIT license

#Binance #blockchain #dotnet #csharp 

Binance Public API Connector in DotNET

Ant Design Blazor: A Set Of Enterprise-class UI Components

Ant Design Blazor

rich set of enterprise-class UI components based on Ant Design and Blazor.

✨ Features

  • 🌈 Enterprise-class UI designed for web applications.
  • 📦 A set of high-quality Blazor components out of the box.
  • 💕 Supports WebAssembly-based client-side and SignalR-based server-side UI event interaction.
  • 🎨 Supports Progressive Web Applications (PWA).
  • 🛡 Build with C#, a multi-paradigm static language for an efficient development experience.
  • ⚙️ .NET Standard 2.1/.NET 5/.NET 6 based, with direct reference to the rich .NET ecosystem.
  • 🎁 Seamless integration with existing ASP.NET Core MVC and Razor Pages projects.

🌈 Online Examples

WebAssembly static hosting examples:

🖥 Environment Support

  • Compatible with .NET Core 3.1 / .NET 5 / .NET 6.
  • Blazor WebAssembly 3.2 / .NET 5 / .NET 6 Release.
  • Supports two-way binding on the server side.
  • Supports WebAssembly static file deployment.
  • Support 4 major browsers engines, and Internet Explorer 11+ (Blazor Server only)
  • Run directly on .NET MAUI / WPF / Windows Forms and other Blazor Hybrid workloads.
  • Run directly on Electron and other Web standards-based environments.
IE / Edge
Edge / IE
Firefox
Firefox
Chrome
Chrome
Safari
Safari
Opera
Opera
Electron
Electron
Edge 16 / IE 11†522571144Chromium 57

Due to WebAssembly restriction, Blazor WebAssembly doesn't support IE browser, but Blazor Server supports IE 11† with additional polyfills. See official documentation.

From .NET 5, IE 11 is no longer officially supported. See Blazor: Updated browser support. Unofficial support is provided by Blazor.Polyfill community project.

💿 Demo

🎨 Design Specification

Regularly synchronize with Official Ant Design specifications, you can check the sync logs online.

Therefore, you can use the custom theme styles of Ant Design directly.

📦 Installation Guide

Create a new project from the dotnet new template AntDesign.Templates

We have provided the dotnet new template to create a Boilerplate project out of the box:

Pro Template

Install the template

$ dotnet new --install AntDesign.Templates

Create the Boilerplate project with the template

$ dotnet new antdesign -o MyAntDesignApp

Options for the template:

OptionsDescriptionTypeDefault
-f | --fullIf specified, generates all pages of Ant Design Proboolfalse
-ho | --hostSpecify the hosting model'wasm' | 'server' | 'hosted''wasm'
--stylesWhether use NodeJS and Less to compile your custom themes.css | lesscss
--no-restoreIf specified, skips the automatic restore of the project on createboolfalse

Import Ant Design Blazor into an existing project

Go to the project folder of the application and install the Nuget package reference

$ dotnet add package AntDesign

Register the services in Program.cs (client-side WebAssembly Blazor)

builder.Services.AddAntDesign();

or Startup.cs (server-side Blazor)

services.AddAntDesign();

Link the static files in wwwroot/index.html (client-side WebAssembly Blazor) or Pages/_Host.cshtml (server-side Blazor)

<link href="_content/AntDesign/css/ant-design-blazor.css" rel="stylesheet" />
<script src="_content/AntDesign/js/ant-design-blazor.js"></script>

Add namespace in _Imports.razor

@using AntDesign

To display the pop-up component dynamically, you need to add the <AntContainer /> component in App.razor.

<Router AppAssembly="@typeof(MainLayout).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <Result Status="404" />
        </LayoutView>
    </NotFound>
</Router>

<AntContainer />   <-- add this component ✨

Finally, it can be referenced in the .razor component!

<Button Type="@ButtonType.Primary">Hello World!</Button>

⌨️ Local Development

  • Install .NET Core SDK 6.0.100 or later.
  • Install Node.js (only for building style files and interoperable TypeScript files)
  • Clone to local development
$ git clone git@github.com:ant-design-blazor/ant-design-blazor.git
$ cd ant-design-blazor
$ npm install
$ dotnet build ./site/AntDesign.Docs.Build/AntDesign.Docs.Build.csproj
$ npm start

Visual Studio 2022 is recommended for development.

🔗 Links

🗺 Roadmap

Check out this issue to learn about our development plans for 2020.

Download Details:
Author: ant-design-blazor
Source Code: https://github.com/ant-design-blazor/ant-design-blazor
License: MIT, Unknown licenses found

#dotnet #aps.net #csharp #blazor 

Ant Design Blazor: A Set Of Enterprise-class UI Components

Bootstrap Blazor: A Set Of Enterprise-class UI Components

Bootstrap Blazor Component

A set of enterprise-class UI components based on Bootstrap and Blazor.

Features

  • Enterprise-class UI designed for web applications.
  • A set of high-quality Blazor components out of the box.
  • Supports WebAssembly-based client-side and SignalR-based server-side UI event interaction.
  • Supports Progressive Web Applications (PWA).
  • Build with C#, a multi-paradigm static language for an efficient development experience.
  • .NET Standard 2.1 based, with direct reference to the rich .NET ecosystem.
  • Supports NET5. (Server-Side, WASM)
  • Seamless integration with existing ASP.NET Core MVC and Razor Pages projects.

Online Examples

website website

Installation Guide

Create a new project from the dotnet new template

  1. Install the template

dotnet new -i Bootstrap.Blazor.Templates::*

  1. Create the Boilerplate project with the template

dotnet new bbapp

Install Bootstrap Blazor Project Template

  1. Download Project Template

Microsoft Market link

  1. Double Click BootstrapBlazor.UITemplate.vsix

Import Bootstrap Blazor into an existing project

  1. Go to the project folder of the application and install the Nuget package reference

dotnet add package BootstrapBlazor

  1. Add the stylesheet javascripts file to your main index file - Pages/_Host.cshtml (Server) or wwwroot/index.html (WebAssembly)

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    . . .
    <link rel="stylesheet" href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css">
</head>
<body>
    . . .
    <script src="_framework/blazor.server.js"></script>
    <script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
</body>
</html>
  1. Open the ~/Startup.cs file in the and register the Bootstrap Blazor service:

C#

namespace BootstrapBlazorAppName
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //more code may be present here
            services.AddBootstrapBlazor();
        }

        //more code may be present here
    }
}

Visual Studio Integration

To create a new Bootstrap Blazor UI for Blazor application, use the Create New Project Wizard. The wizard detects all installed versions of Bootstrap Blazor for Blazor and lists them in the Version combobox—this enables you to start your project with the desired version. You can also get the latest version to make sure you are up to date.

  1. Get the Wizard

To use the Create New Project Wizard, install the Bootstrap Blazor UI for Blazor Visual Studio Extensions. You can get it from the:

  • Visual Studio Marketplace (for Windows)
  1. Start the Wizard

To start the wizard, use either of the following approaches

Using the Project menu:

  • Click File > New > Project.
  • Find and click the C# Blazor Application option (you can use the search, or filter by Blazor templates).
  • Follow the wizard.

Supported browsers

Mobile devices  

 ChromeFirefoxSafariAndroid Browser & WebViewMicrosoft Edge
iOSSupportedSupportedSupportedN/ASupported
AndroidSupportedSupportedN/AAndroid v5.0+ supportedSupported
Windows 10 MobileN/AN/AN/AN/ASupported

Desktop browsers

 ChromeFirefoxInternet ExplorerMicrosoft EdgeOperaSafari
MacSupportedSupportedN/AN/ASupportedSupported
LinuxSupportedSupportedN/AN/AN/AN/A
WindowsSupportedSupportedSupported, IE11+SupportedSupportedNot supported

Screenshots

Toggle Toast Upload Upload2 Bar Pei Doughnut

Contribution

  1. Fork
  2. Create Feat_xxx branch
  3. Commit
  4. Create Pull Request

Download Details:
Author: dotnetcore
Source Code: https://github.com/dotnetcore/BootstrapBlazor
License: Apache-2.0 license

#dotnet #aps.net #csharp #blazor #bootstrap

Bootstrap Blazor: A Set Of Enterprise-class UI Components

Logibit Hawk: A F# Implementation Of The Hawk Authentication Protocol

Logibit Hawk

A F# implementation of the Hawk authentication protocol. Few dependencies. No cruft. No thrown exceptions.

If this library throws an exception, report an issue - instead it uses return values that are structured instead.

paket add nuget Hawk
paket add nuget Hawk.Suave

Dependencies: { Aether, FSharp.Core, NodaTime }, nugets Hawk and Hawk.Suave.

For all API methods implemented, the full test suite for those methods has also been translated.

Sponsored by qvitoo – A.I. bookkeeping.

Usage (Suave Example)

open Logibit.Hawk
open Logibit.Hawk.Types
open Logibit.Hawk.Server

open Suave
open Suave.Http // houses submodule 'Hawk'
open Suave.Http.Successful
open Suave.Http.RequestErrors
open Suave.Types

// your own user type
type User =
  { homepage  : Uri
    realName : string }

// this is the structure that is the 'context' for Logibit.Hawk
let settings =
  // this is what the lib is looking for to verify the request
  let sampleCreds =
    { id        = "haf"
      key       = "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn"
      algorithm = SHA256 }

  // the generic type param allows you to implement a generic user repository
  // for your own user type (above)
  { Settings.empty<User>() with
     // sign: UserId -> Choice<Credentials * 'a, CredsError>
     credsRepo = fun id ->
       (sampleCreds,
        { homepage = Uri("https://qvitoo.com"); realName = "Henrik" }
       )
       // no error:
       |> Choice1Of2 }

// You can compose this into the rest of the app, as it's a web part. In this
// case you're doing a Authorization header authentication
let sampleApp settings : WebPart =
  Hawk.authenticate
    settings
    Hawk.bindHeaderReq
    // in here you can put your authenticated web parts
    (fun (attr, creds, user) -> OK (sprintf "authenticated user '%s'" user.realName))
    // on failure to authenticate the request
    (fun err -> UNAUTHORIZED (err.ToString()))

// Similarly for bewits, where you want to authenticate a portion of the query
// string:
let sampleApp2 settings : WebPart =
  Hawk.authenticateBewit
    settings Hawk.bindQueryRequest
    // in here you can put your authenticated web parts
    (fun (attr, creds, user) -> OK (sprintf "authenticated user '%s'" user.realName))
    // on failure to authenticate the request
    (fun err -> UNAUTHORIZED (err.ToString()))

Currently the code is only fully documented - but not outside the code, so have a browse to the source code that you are interested in to see how the API composes.

Usage from client:

Use the .js file from src/vendor/hawk.js/lib, then you can wrap your ajax calls like this:

request.js: (using CommonJS module layout, which you can use to require it and get a function in return).

var Auth   = require('./auth.js'),
    Hawk   = require('./lib/hawk.js'),
    Logger = require('./logger.js'),
    jQuery = require('jquery');

var qt = function(str) {
  return "'" + str + "'";
}

var jqSetHawkHeader = function(opts, creds, jqXHR, settings) {
  if (typeof opts.contentType == 'undefined') {
    throw new Error('missing contentType from options');
  }

  var opts = jQuery.extend({ credentials: creds, payload: settings.data }, opts),
      // header(uri, method, options): should have options values for
      // - contentType
      // - credentials
      // - payload
      header = Hawk.client.header(settings.url, settings.type, opts); // type = HTTP-method

  if (typeof header.err !== 'undefined') {
    Logger.error('(1/2) Hawk error:', qt(header.err), 'for', method, qt(settings.url));
    Logger.error('(2/2) Using credentials', opts.credentials);
    return;
  }

  Logger.debug('(1/3)', settings.type, settings.url);
  Logger.debug('(2/3) opts:', opts);
  Logger.debug('(3/3) header:', header.field);

  jqXHR.setRequestHeader('Authorization', header.field);
};

module.exports = function (method, resource, data, opts) {
  var origin    = window.location.origin,
      creds     = Auth.getCredentials(),
      url       = origin + resource,
      opts      = jQuery.extend({
        contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
        dataType: 'html'
      }, (typeof opts !== 'undefined' ? opts : {})),
      jqOpts    = jQuery.extend({
        type:       method,
        data:       data,
        url:        url,
        beforeSend: function(xhr, s) { jqSetHawkHeader(opts, creds, xhr, s) }
      }, opts);

  return jQuery.ajax(jqOpts);
};

Changelog

Please have a look at Releases.

API

This is the public API of the library. It mimics the API of Hawk.js - the reference implementation.

Logibit.Hawk.Bewit

These functions are available to creating and verifying Bewits.

  •  generate - generate a new bewit from credentials, a uri and an optional ext field.
  •  generate' - generate a new bewit from credentials, a string uri and an optional ext field.
  •  authenticate - verify a given bewit

authenticate details

TBD - docs, in the meanwhilse, see Server authenticate (superset is validated).

Logibit.Hawk.Client

These functions are available, checked functions are implemented

  •  header - generate a request header for server to authenticate
  •  bewit - delegates to Bewit.generate
  •  authenticate - test that server response is authentic, see Response Payload Validation.
  •  message - generate an authorisation string for a message

Logibit.Hawk.Server

  •  authenticate - authenticate a request
  •  authenticatePayload - authenticate the payload of a request - assumes you first have called authenticate to get credentials. Payload Validation
  •  authenticatePayloadHash
  •  header - generate a server-header for the client to authenticate
  •  authenticateBewit - authenticate a client-supplied bewit, see Bewit Usage Example.
  •  authenticateMessage - authenticate a client-supplied message

authenticate details

How strictly does the server validate its input? Compared to reference implementation. This part is important since it will make or break the usability of your api/app. Just throwing SecurityException for any of these is not granular enough.

  •  server cannot parse header -> FaultyAuthorizationHeader
  •  server cannot find Hawk scheme in header -> FaultyAuthorizationHeader
  •  id, ts, nonce and mac (required attrs) are supplied -> MissingAttribute
  •  credential function errors -> CredsError
  •  mac doesn't match payload -> BadMac
  •  missing payload hash if payload -> MissingAttribute
  •  payload hash not matching -> BadPayloadHash of hash_given * hash_calculated
  •  nonce reused -> NonceError AlreadySeen, with in-memory cache
  •  stale timestamp -> StaleTimestamp

Hints when not under attack (in dev)

If you see CredsError, it's most likely a problem that you can't find the user with your repository function.

If you see BadMac, it means probably means you haven't fed the right parameters to authenticate. Log the input parameters, verify that host and port match (are you behind a reverse proxy?) and check that the length of the content is the same on the client as on the server.

The BadMac error comes from hashing a normalised string of these parameters:

  • hawk header version
  • type of normalisation ('header' in this case)
  • timestamp
  • nonce
  • method
  • resource (aka PathAndQuery for the constructed Uri)
  • host
  • port
  • hash value
  • ext if there is one
  • app if there is one
  • dlg if there is app and if there is one

If you see PadPayloadHash, it means that the MAC check passed, so you're probably looking at an empty byte array, or your Content-Type isn't being passed to the server properly, or the server implementation doesn't feed the correct Content-Type header (e.g. it doesn't trim the stuff after the first MimeType declaration, before the semi-colon ;).

Logibit.Hawk.Crypto

The crypto module contains functions for validating the pieces of the request.

  •  genNormStr - generate a normalised string for a request/auth data
  •  calcPayloadHash - calculates the payload hash from a given byte[]
  •  calcPayloadHash - calculates the payload hash from a given string
  •  calcHmac - calculates the HMAC for a given string

Logibit.Hawk.Types

This module contains the shared types that you should use for interacting with the above modules.

  • HttpMethod - discriminated union type of HTTP methods
  • Algo - The supported hash algorithms
  • Credentials - The credentials object used in both client and server
  • HawkAttributes - Recognised attributes in the Hawk header
  • FullAuth - A structure that represents the fully calculated hawk request data structure

This module also contains a module-per-type with lenses for that type. The lenses follow the same format as Aether recommends.

Logibit.Hawk.Logging

Types:

  • LogLevel - the level of the LogLine.
  • LogLine - this is the data structure of the logging module, this is where you feed your data.
  • Logger interface - the main interface that we can log to/into.
  • Logger module - a module that contains functions equiv. to the instance methods of the logger interface.
  • NoopLogger : Logger - the default logger, you have to replace it yourself

It's good to know that you have to construct your LogLine yourself. That LogLines with Verbose or Debug levels should be sent to the debug or verbose functions/methods of the module/interface Logger, which in turn takes functions, which are evaluated if it's the case that the logging infrastructure is indeed logging at that level.

This means that logging at that level, and computing the log lines, needs only be done if we can really do something with them.

Other APIs

There are some modules that are currently internal as to avoid conflicting with existing code. If these are made 'more coherent' or else moved to external libraries, they can be placed on their own and be made public. The modules like this are Random, Prelude, Parse.

Download Details:
Author: logibit
Source Code: https://github.com/logibit/logibit.hawk/
License: View license

#dotnet #aps.net #csharp

Logibit Hawk: A F# Implementation Of The Hawk Authentication Protocol

AspNetSaml: Very Simple SAML 2.0 Consumer Module for ASP.NET/C#

AspNetSaml

Very simple SAML 2.0 "consumer" implementation in C#.

It's a SAML client library, not a SAML server, allows adding SAML single-sign-on to your ASP.NET app, but not to provide auth services to other apps.

Installation

Consists of one short C# file you can throw into your project (or install via nuget) and start using it. It works with both ASP.NET Core and the "old" ASP.NET Framework

Usage

How SAML works?

SAML workflow has 2 steps:

  1. User is redirected to the SAML provider (where he authenticates)
  2. User is redirected back to your app, where you validate the payload

Here's how you do it (this example is for ASP.NET MVC):

1. Redirecting the user to the saml provider:

//this example is an ASP.NET MVC action method
public ActionResult Login()
{
    //TODO: specify the SAML provider url here, aka "Endpoint"
    var samlEndpoint = "http://saml-provider-that-we-use.com/login/";

    var request = new AuthRequest(
        "http://www.myapp.com", //TODO: put your app's "entity ID" here
        "http://www.myapp.com/SamlConsume" //TODO: put Assertion Consumer URL (where the provider should redirect users after authenticating)
        );

    //redirect the user to the SAML provider
    return Redirect(request.GetRedirectUrl(samlEndpoint));
}

2. User has been redirected back

User is sent back to your app - you need to validate the SAML response ("assertion") that you recieved via POST.

Here's an example of how you do it in ASP.NET MVC

//ASP.NET MVC action method... But you can easily modify the code for Web-forms etc.
public ActionResult SamlConsume()
{
    // 1. TODO: specify the certificate that your SAML provider gave you
    string samlCertificate = @"-----BEGIN CERTIFICATE-----
BLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAH123543==
-----END CERTIFICATE-----";

    // 2. Let's read the data - SAML providers usually POST it into the "SAMLResponse" var
    var samlResponse = new Response(samlCertificate, Request.Form["SAMLResponse"]);

    // 3. We're done!
    if (samlResponse.IsValid())
    {
        //WOOHOO!!! user is logged in
        username = samlResponse.GetNameID();
    }
}

Reading more attributes from the provider

SAML providers usually send more data with their response: username, first/last names etc. Here's how to get it:

if (samlResponse.IsValid())
{
    //WOOHOO!!! user is logged in

    //Some more optional stuff for you
    //let's extract username/firstname etc
    string username, email, firstname, lastname;
    try
    {
        username = samlResponse.GetNameID();
        email = samlResponse.GetEmail();
        firstname = samlResponse.GetFirstName();
        lastname = samlResponse.GetLastName();
    }
    catch(Exception ex)
    {
        //insert error handling code
        //no, really, please do
        return null;
    }

    //user has been authenticated, put your code here, like set a cookie or something...
    //or call FormsAuthentication.SetAuthCookie()
    //or call context.SignInAsync() in ASP.NET Core
    //or do something else
}

Dependencies

Depending on your .NET version, your Project should reference System.Security for .NET Framework and System.Security.Cryptography.Xml for .NET Core.

(NEW!) Nuget

I've published this to Nuget.

Install-Package AspNetSaml

This will simply add the cs-file to the root of your project.

A version of this library has been used for years in production in our helpdesk app.

Download Details:
Author: jitbit
Source Code: https://github.com/jitbit/AspNetSaml
License: Apache-2.0 license

#dotnet #aps.net #csharp 

AspNetSaml: Very Simple SAML 2.0 Consumer Module for ASP.NET/C#

Bundle Transformer: A Modular Extension for System.Web.Optimization

Bundle Transformer

Bundle Transformer - a modular extension for the System.Web.Optimization (also known as the Microsoft ASP.NET Web Optimization Framework). StyleTransformer and ScriptTransformer classes, included in the core of Bundle Transformer and implement the IBundleTransform interface. They are intended to replace the standard classes: CssMinify and JsMinify.

The main differences of the StyleTransformer and ScriptTransformer classes from a standard implementations: ability to exclude unnecessary assets when adding assets from a directory, does not produce the re-minification of pre-minified assets, support automatic transformation of relative paths to absolute in CSS code (by using the UrlRewritingCssPostProcessor), etc. These classes do not produce the minification of code in runtime, but this feature can be added by installing of minifier-modules (now available modules based on Microsoft Ajax Minifier, YUI Compressor for .NET, NUglify, Google Closure Compiler, Douglas Crockford's JSMin, Dean Edwards' Packer, Mihai Bazon's UglifyJS, Sergey Kryzhanovsky's CSSO (CSS Optimizer), WebGrease and Clean-css). In addition, you can also install translator-modules, that implement the translation of code on intermediate languages (LESS, Sass, SCSS, CoffeeScript, TypeScript, Mustache (by using Hogan) and Handlebars). Apart from this, in the Bundle Transformer there is a third type of modules - postprocessors. Postprocessors runs after translators and before minifiers. Now available following postprocessors: URL rewriting CSS postprocessor (included in core) and postprocessor-module based on the Andrey Sitnik's Autoprefixer.

This extension will help your web applications successfully pass a most part of the tests in Google PageSpeed.

NuGet Packages

Core

Translators

Postprocessors

Minifiers

Unofficial modules

Documentation

Documentation is located on the wiki of this Repo.

Release History

See the changelog.

Who's Using Bundle Transformer

If you use Bundle Transformer in some project, please send me a message so I can include it in this list:

Software

Websites

Bundle Transformer was created and is maintained by Andrey Taritsyn.

Download Details:
Author: Taritsyn
Source Code: https://github.com/Taritsyn/BundleTransformer
License: Apache-2.0 license

#dotnet #aps.net #csharp 

Bundle Transformer: A Modular Extension for System.Web.Optimization
Best of Crypto

Best of Crypto

1656507369

Binance DotNet: C# Wrapper for The Binance Exchange API

BinanceDotNet

C# Wrapper for the official Binance exchange API

Compatible with .NET 4.5.1, .NET 4.5.2, .NET 4.6.1, .NETSTANDARD2.0

This repository provides a C# wrapper for the official Binance API, and provides rate limiting features (set to 10 by 10 out the box), a IAPICacheManager interface to allow users to provide their own cache implementations, all REST endpoints covered, and a best practice solution coupled with strongly typed responses and requests. It is built on the latest .NET Framework and in .NET Core

Feel free to raise issues and Pull Request to help improve the library. If you found this API useful, and you wanted to give back feel free to sign up to Binance via my referral link here.

Documentation

Installation

The package is available in NuGet, or feel free to download: https://www.nuget.org/packages/BinanceDotNet/

Nuget PM

Install-Package BinanceDotNet

dotnet cli

dotnet add package BinanceDotNet

Donations and Contribution

Upkeep of this API takes a lot of time from answering issues and PR's on the Repository, as well as tweets and direct emails. You can donate cryptocurrency of any amount to the following wallets:

ETH: 0xd5775e2dee4b9fa9a3be5222970c04ac574e8412

Want to send something else? Just tweet me! @Glitch100

Or you can help maintain the repository! Donations of time are welcome, just hit me up and we can work on it. From answering issues, to contributing code anyone can assist.

git clone git@github.com:glitch100/BinanceDotNet.git
  • Navigate to ExampleProgram.cs
  • Add your own Private and Secret keys
  • Play around with the API

Features

  • Simple, Configurable, Extendable
  • Rate limiting, with 10 requests in 10 seconds (disabled by default)
  • log4net Interfaces supported
  • dotnet standard, dotnet core, 4.5.1, 4.6.1 support
  • Binance WebSockets
  • Unit test coverage (in progress)
  • IAPICacheManager abstraction for providing your own cache or using the build in concrete implementation. (Currently only one endpoint has caching)
  • Console app with examples ready to launch (provide API keys)

Examples

More examples are available to play around with within the repositorys Console application which can be found here. Otherwise there are some examples around utilising both WebSockets and REST API in the Usage section below.

Roadmap

Work will continue on this API wrapper over the coming months adding and extending out the number of features that the BinanceDotNet library has. Please raise issues for new features desired

  • Start building out Unit Test support - >~2.1.0
  • Provide Builder support for queries - 2.5.0~
  • Abstract out the HttpClient - 3.0.0~

Usage

Code examples below, or clone the repository and run the BinanceExchange.Console project. This repository is built off dotnet core, and runs against C# 7.1

Creating a Client

General usage just requires setting up the client with your credentials, and then calling the Client as necessary.

// Build out a client, provide a logger, and more configuration options, or even your own APIProcessor implementation
var client = new BinanceClient(new ClientConfiguration()
{
    ApiKey = "YOUR_API_KEY",
    SecretKey = "YOUR_SECRET_KEY",
});

//You an also specify symbols like this.
var desiredSymbol = TradingPairSymbols.BNBPairs.BNB_BTC,

IReponse response = await client.GetCompressedAggregateTrades(new GetCompressedAggregateTradesRequest(){
  Symbol = "BNBBTC",
  StartTime = DateTime.UtcNow().AddDays(-1),
  EndTime = Date.UtcNow(),
});

Creating a WebSocket Client

For WebSocket endpoints, just instantiate the BinanceClient, and provide it into the BinanceWebSocketClient You can use a using block or manual management.

var client = new BinanceClient(new ClientConfiguration()
{
    ApiKey = "YOUR_API_KEY",
    SecretKey = "YOUR_SECRET_KEY",
});


// Manual management
var manualWebSocketClient = new InstanceBinanceWebSocketClient(client);
var socketId = binanceWebSocketClient.ConnectToDepthWebSocket("ETHBTC", data =>
{
    System.Console.WriteLine($"DepthCall: {JsonConvert.SerializeObject(data)}");
});
manualWebSocketClient.CloseWebSocketInstance(socketId);


// Disposable and managed
using (var binanceWebSocketClient = new DisposableBinanceWebSocketClient(client))
{
    binanceWebSocketClient.ConnectToDepthWebSocket("ETHBTC", data =>
    {
        System.Console.WriteLine($"DepthCall: {JsonConvert.SerializeObject(data)}");
    });

    Thread.Sleep(180000);
}

Error Handling

The Binance API provides rich exceptions based on different error types. You can decorate calls like this if you would like to handle the various exceptions.

// Firing off a request and catching all the different exception types.
try
{
    accountTrades = await client.GetAccountTrades(new AllTradesRequest()
    {
        FromId = 352262,
        Symbol = "ETHBTC",
    });
}
catch (BinanceBadRequestException badRequestException)
{

}
catch (BinanceServerException serverException)
{

}
catch (BinanceTimeoutException timeoutException)
{

}
catch (BinanceException unknownException)
{
}

Building out a local cache per symbol from the depth WebSocket

The example is mainly 'all in one' so you can see a full runthrough of how it works. In your own implementations you may want to have a cache of only the most recent bids/asks, or perhaps will want the empty quanity/price trades.

You can also calculate volume and more from this cache. The following code is partial from the ExampleProgram.cs.

private static async Task<Dictionary<string, DepthCacheObject>> BuildLocalDepthCache(IBinanceClient client)
{
    // Code example of building out a Dictionary local cache for a symbol using deltas from the WebSocket
    var localDepthCache = new Dictionary<string, DepthCacheObject> {{ "BNBBTC", new DepthCacheObject()
    {
        Asks = new Dictionary<decimal, decimal>(),
        Bids = new Dictionary<decimal, decimal>(),
    }}};
    var bnbBtcDepthCache = localDepthCache["BNBBTC"];

    // Get Order Book, and use Cache
    var depthResults = await client.GetOrderBook("BNBBTC", true, 100);
    //Populate our depth cache
    depthResults.Asks.ForEach(a =>
    {
        if (a.Quantity != 0.00000000M)
        {
            bnbBtcDepthCache.Asks.Add(a.Price, a.Quantity);
        }
    });
    depthResults.Bids.ForEach(a =>
    {
        if (a.Quantity != 0.00000000M)
        {
            bnbBtcDepthCache.Bids.Add(a.Price, a.Quantity);
        }
    });

    // Store the last update from our result set;
    long lastUpdateId = depthResults.LastUpdateId;
    using (var binanceWebSocketClient = new DisposableBinanceWebSocketClient(client))
    {
        binanceWebSocketClient.ConnectToDepthWebSocket("BNBBTC", data =>
        {
            if (lastUpdateId < data.UpdateId)
            {
                data.BidDepthDeltas.ForEach((bd) =>
                {
                    CorrectlyUpdateDepthCache(bd, bnbBtcDepthCache.Bids);
                });
                data.AskDepthDeltas.ForEach((ad) =>
                {
                    CorrectlyUpdateDepthCache(ad, bnbBtcDepthCache.Asks);
                });
            }
            lastUpdateId = data.UpdateId;
            System.Console.Clear();
            System.Console.WriteLine($"{JsonConvert.SerializeObject(bnbBtcDepthCache, Formatting.Indented)}");
            System.Console.SetWindowPosition(0, 0);
        });

        Thread.Sleep(8000);
    }
    return localDepthCache;
}

Result Transformations

You can use the data returned from above to utilise the ResultTransformations static class, to transform data returned from the API into more meaningful, known shapes, such as Volume etc.

// This builds a local depth cache from an initial call to the API and then continues to fill
// the cache with data from the WebSocket
var localDepthCache = await BuildLocalDepthCache(client);
// Build the Buy Sell volume from the results
var volume = ResultTransformations.CalculateTradeVolumeFromDepth("BNBBTC", localDepthCache);

Download Details:
Author: binance-exchange
Source Code: https://github.com/binance-exchange/BinanceDotNet
License: MIT license

#Binance #blockchain #dotnet #csharp 

Binance DotNet: C# Wrapper for The Binance Exchange API

DotNetty: Asynchronous Event-driven Network Application Framework

DotNetty Project

DotNetty is a port of Netty, asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.

Use

  • Official releases are on NuGet.
  • Nightly builds are available on MyGet.

Contribute

We gladly accept community contributions.

Download Details:
Author: Azure
Source Code: https://github.com/Azure/DotNetty
License: View license

#dotnet #aps.net #csharp 

DotNetty: Asynchronous Event-driven Network Application Framework
Corey Brooks

Corey Brooks

1656386666

How to Adds an API to Your Website with ASP.NET Core

Learn C# with CSharpFritz - Add an API to your Website with C#

Fritz has built a website to manage your collection, but how can we open up the website with an API to allow other integrations?  In this session, Fritz adds an API to our website using ASP.NET Core

#aspnetcore #api #dotnet #csharp #webdev 

How to Adds an API to Your Website with ASP.NET Core
Oral  Brekke

Oral Brekke

1656050040

.NET Version Of The Playwright Testing and Automation Library

Playwright for .NET 🎭 

Playwright for .NET is the official language port of Playwright, the library to automate Chromium, Firefox and WebKit with a single API. Playwright is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.

 LinuxmacOSWindows
Chromium 103.0.5060.24
WebKit 15.4
Firefox 99.0.1

API Reference

https://playwright.dev/dotnet/docs/api/class-playwright

using System.Threading.Tasks;
using Microsoft.Playwright;

class Program
{
    public static async Task Main()
    {
        using var playwright = await Playwright.CreateAsync();
        await using var browser = await playwright.Chromium.LaunchAsync(new() { Headless = false });
        var page = await browser.NewPageAsync();
        await page.GotoAsync("https://playwright.dev/dotnet");
        await page.ScreenshotAsync(new() { Path = "screenshot.png" });
    }
}

Other languages

More comfortable in another programming language? Playwright is also available in

Documentation

https://playwright.dev/dotnet/docs/intro

Author: Microsoft
Source Code: https://github.com/microsoft/playwright-dotnet 
License: MIT license

#node #playwright #dotnet 

.NET Version Of The Playwright Testing and Automation Library
坂本  健一

坂本 健一

1655982600

.NET Core MVCWebAPIのSwagger

Swagger(OpenAPI)は、RESTAPIを記述するための言語に依存しない仕様です。これにより、コンピューターと人間の両方が、ソースコードに直接アクセスしなくてもRESTAPIの機能を理解できます。Swagger UIは、生成されたOpenAPI仕様を使用して、サービスに関する情報を提供するWebベースのUIを提供します。SwaggerUIはPostmanの代替手段です。

私は自分の記事でSwaggerを数回以上使用しましたが、さまざまなトピックで使用されるマイナーなツールとして使用しました。Swaggerの情報を取得しようとしたとき、これらの記事から検索する必要がありましたが、これは便利ではありませんでした。そこで、これら2つの記事、特にSwagger for .NET MVCWebAPIまたは.NETCoreMVCWebAPIについて書き直しました。

序章

新しい.NETCore5.0 Web APIプロジェクトを作成した場合、WebAPI用のSwaggercientがデフォルトでインストールされます。現在のケースでは、.NET Core 5.0を使用していますが、Web APIはMVCモジュールで作成されているため、Swaggerを手動でインストールする必要があります。この方法は、5.0より前の.NETCoreバージョンで機能します。

この記事は、私の別の記事の一部です 。MVCによるWeb APIの使用.NETCore(1)、サーバー、およびフレームワークでは、Swagger関連の部分がここにあります。そこから詳細を見ることができます。

ステップ1-ASP.NETCoreMVCアプリケーションを作成する

アプリのビルドには、Visual Studio201916.8と.NET5.0SDKのバージョンを使用します。

  1. Visual Studioを起動し、[新しいプロジェクトの作成]を選択します。
  2. [新しいプロジェクトの作成]ダイアログで、[ASP.NETCoreWebアプリケーション]>[次へ]を選択します。
  3. [新しいプロジェクトの構成]ダイアログで、 MVCCallWebAPI プロジェクト名を入力します。
  4. [作成]を選択します。
  5. [新しいASP.NETCoreWebアプリケーションの作成]ダイアログで、[次のコマンドを選択します。
    1. ドロップダウンの.NETCoreおよびASP.NETCore5.0。
    2. ASP.NET Core Webアプリ(Model-View-Controller)。
    3. 作成

アプリをビルドして実行すると、次の画像にアプリが表示されます。

ステップ2〜3-EntityFrameworkを使用したアクションを備えたScaffoldAPIコントローラー

記事「 .NETCore(1)、サーバーおよびフレームワークでMVCによるWebAPIの消費」を参照してください 。

B:最初にEntityFrameworkコードを使用してWebAPIを追加する

  • ステップ1:新しいデータベースコンテキストを設定する
  • ステップ2:EntityFrameworkコードの最初のアプローチを使用してデータベースを操作します。
  • ステップ3、:EntityFrameworkを使用したアクションを備えたScaffoldAPIコントローラー

ステップ4-WebAPI用のSwaggerクライアントを追加する

1.Swaggerクライアントをインストールします

ソリューションエクスプローラー>[NuGetパッケージの管理]でプロジェクトを右クリックし、  Swaggerを検索します

Swashbuckle(Swagger)には3つの主要なコンポーネントがあり、そのうちの2つをインストールするだけで済みます。SwaggerGenとSwaggerUIで、Swaggerが含まれます。

2.startup.cs ファイルにSwaggerクライアントを登録し ます

Startup.ConfigureServices メソッドのサービスコレクションにSwaggerジェネレーターを追加します 。

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v2", new OpenApiInfo { Title = "MVCCallWebAPI", Version = "v2" });
    });
    ......
}

Startup.Configure メソッドで、生成されたJSONドキュメントとSwaggerUIを提供するためのミドルウェアを有効にします 。

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v2/swagger.json", "MVCCallWebAPI");
    });
    ......
}

これで、アプリを実行する準備がほぼ整いました。

ステップ5-アプリを実行してテストする

アプリを実行する前に、ファイルのヘッダーを変更します 。Views/ Shared / _layout.cshtml  Viewsを再度変更して、以下に示すSwagger(11〜13行目)を追加します。

<header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
        <div class="container">
            <a class="navbar-brand" asp-area="" asp-controller="StoresMVC" asp-action="Index">MVC app</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Swagger" asp-action="Index">Web API</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</header>

次に、アプリを実行します。

Web APIをクリックすると、Swaggerクライアント画面が表示されます。

 

ソース:https ://www.c-sharpcorner.com/article/swagger-for-net-core-mvc-web-api/

#dotnet #netcore #mvc #webapi #swagger 

 .NET Core MVCWebAPIのSwagger

Swagger para .NET Core MVC Web API

Swagger (OpenAPI) é uma especificação independente de linguagem para descrever APIs REST. Ele permite que computadores e humanos entendam os recursos de uma API REST sem acesso direto ao código-fonte. Swagger UI oferece uma UI baseada na web que fornece informações sobre o serviço, usando a especificação OpenAPI gerada. Swagger UI é uma alternativa ao Postman.

Usei o Swagger várias vezes em meus artigos, mas apenas como uma ferramenta menor usada em diferentes tópicos. Quando tentei obter informações do Swagger, tive que pesquisar nesses artigos, que não eram convenientes. Então, reescrevo esses dois artigos, especialmente sobre Swagger para .NET MVC Web API ou .NET Core MVC Web API.

Introdução

Se tivéssemos criado um novo projeto de API Web .NET Core 5.0, o Swagger cient for Web API seria instalado por padrão. Em nosso caso atual, embora usemos o .NET Core 5.0, a API da Web é criada em um módulo MVC, portanto, precisamos instalar o Swagger manualmente. Dessa forma, funcionará para a versão .NET Core anterior à 5.0.

Este artigo é parte do meu outro artigo:  Consumir Web API por MVC No .NET Core (1), Server And Framework , temos aqui a parte relacionada ao Swagger. Você pode ver detalhes de lá.

Etapa 1 - Criar um aplicativo ASP.NET Core MVC

Usamos a versão do Visual Studio 2019 16.8 e .NET 5.0 SDK para compilar o aplicativo.

  1. Inicie o Visual Studio e selecione Criar um novo projeto.
  2. Na caixa de diálogo Criar um novo projeto, selecione Aplicativo Web ASP.NET Core > Avançar.
  3. Na caixa de diálogo Configurar seu novo projeto, insira  MVCCallWebAPI o nome do projeto.
  4. Selecione Criar.
  5. Na caixa de diálogo Criar um novo aplicativo Web ASP.NET Core, selecione,
    1. .NET Core e ASP.NET Core 5.0 nas listas suspensas.
    2. Aplicativo Web ASP.NET Core (Model-View-Controller).
    3. Crio

Compile e execute o aplicativo, você verá a imagem a seguir mostra o aplicativo,

Etapa 2~3 - Controlador de API do Scaffold com Ação usando o Entity Framework

Consulte o artigo  Consume Web API By MVC In .NET Core (1), Server And Framework ,

B: Adicione a API da Web com o código do Entity Framework primeiro

  • Etapa 1: configurar um novo contexto de banco de dados
  • Etapa 2: trabalhar com um banco de dados usando o primeiro aplicativo de código do Entity Framework.
  • Etapa 3,:Scaffold API Controller com Action usando Entity Framework

Etapa 4 - Adicionar cliente Swagger para API da Web

1. Instale o cliente Swagger

Clique com o botão direito do mouse no projeto em Solution Explorer > Manage NuGet Packages, procure  Swagger

Existem três componentes principais para o Swashbuckle (Swagger), precisamos apenas instalar dois deles: SwaggerGen e SwaggerUI, o Swagger seria incluído.

2. Registre o Swagger Client no   arquivo startup.cs

Adicione o gerador Swagger à coleção de serviços no  Startup.ConfigureServices método,

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Register the Swagger generator, defining 1 or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v2", new OpenApiInfo { Title = "MVCCallWebAPI", Version = "v2" });
    });
    ......
}

Habilite o middleware para servir o documento JSON gerado e a UI Swagger, no  Startup.Configure método,

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // Enable middleware to serve generated Swagger as a JSON endpoint.
    app.UseSwagger();

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
    // specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v2/swagger.json", "MVCCallWebAPI");
    });
    ......
}

Agora, estamos quase prontos para executar o aplicativo.

Etapa 5 - Executar e testar o aplicativo

Antes de executarmos o aplicativo, modifique o cabeçalho do arquivo:  Views/Shared/_layout.cshtml  Views novamente para adicionar Swagger (linha 11~13), mostrado abaixo,

<header>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
        <div class="container">
            <a class="navbar-brand" asp-area="" asp-controller="StoresMVC" asp-action="Index">MVC app</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Swagger" asp-action="Index">Web API</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</header>

Agora, executamos o aplicativo,

Clique em Web API, temos a tela do Swagger Client,

 

Fonte: https://www.c-sharpcorner.com/article/swagger-for-net-core-mvc-web-api/

#dotnet #netcore #mvc #webapi 

Swagger para .NET Core MVC Web API
Léon  Peltier

Léon Peltier

1655929800

Implémentation du Cache Redis dans l'API .NET Core

Nous allons discuter de la mise en cache dans .NET Core et de son fonctionnement. Donc, nous regardons les choses suivantes une par une.

  • Présentation de la mise en cache
  • Qu'est-ce que le cache
  • Types de cache
  • Implémentation du cache

Alors, commençons un par un.

Introduction

La mise en cache est très populaire de nos jours dans l'industrie du logiciel car elle améliore les performances et l'évolutivité de l'application. Nous utilisons de nombreuses applications Web comme Gmail et Facebook et voyons à quel point elles sont réactives et nous avons une excellente expérience utilisateur. De nombreux utilisateurs utilisent Internet et si une application a un trafic réseau et une demande énormes, nous devons nous occuper de beaucoup de choses qui nous aident à améliorer les performances et la réactivité de l'application. Donc, à cause de cela, il y a la solution de la mise en cache et c'est pourquoi la mise en cache entre en jeu.

Qu'est-ce que la mise en cache ?

Le cache est le stockage de mémoire utilisé pour stocker les données d'accès fréquentes dans le stockage temporaire, il améliorera considérablement les performances et évitera les accès inutiles à la base de données et stockera les données fréquemment utilisées dans le tampon chaque fois que nous en aurons besoin.

Comme vous le voyez dans l'image ci-dessus, il existe deux scénarios, l'un sans utiliser de cache et l'autre avec cache. Donc, ici, lorsque nous n'utilisons pas le cache, dans ce cas, supposons que les utilisateurs veulent des données, ils frapperont à chaque fois la base de données et cela augmentera la complexité temporelle et réduira les performances au cas où il y aurait des données statiques que les utilisateurs voudraient et c'est la même chose pour tous les utilisateurs. Dans ce cas, lorsque nous n'utilisons pas de cache, chacun accède à la base de données inutile pour récupérer des données. De l'autre côté, comme vous pouvez le voir, nous utilisons le cache, et dans ce cas s'il y a les mêmes données statiques et les mêmes pour tous les utilisateurs, seul le premier utilisateur accédera à la base de données et récupérera les données et les stockera dans la mémoire cache, puis deux autres utilisateurs l'ont utilisé à partir du cache sans toucher inutilement à la base de données pour récupérer des données.

Types de cache

Fondamentalement, il existe deux types de prise en charge de la mise en cache de .NET Core

  1. Mise en cache en mémoire
  2. Mise en cache distribuée

Lorsque nous utilisons le cache en mémoire, dans ce cas, les données sont stockées dans la mémoire du serveur d'applications et chaque fois que nous en avons besoin, nous récupérons les données et les utilisons partout où nous en avons besoin. Et dans la mise en cache distribuée, il existe de nombreux mécanismes tiers comme Redis et bien d'autres. Mais dans cette section, nous examinons en détail le cache Redis et son fonctionnement dans .NET Core

Mise en cache distribuée

  • Fondamentalement, dans le cache distribué, les données sont stockées et partagées entre plusieurs serveurs
  • De plus, il est facile d'améliorer l'évolutivité et les performances de l'application après avoir géré la charge entre plusieurs serveurs lorsque nous utilisons une application multi-locataire
  • Supposons qu'à l'avenir, si un serveur tombe en panne et redémarre, l'application n'a aucun impact car plusieurs serveurs répondent à nos besoins si nous le voulons.

Redis est le cache le plus populaire utilisé par de nombreuses entreprises de nos jours pour améliorer les performances et l'évolutivité de l'application. Nous allons donc discuter de Redis et de son utilisation un par un.

Cache Redis

  • Redis est un magasin de structure de données en mémoire Open Source (sous licence BSD) utilisé comme base de données.
  • Fondamentalement, il est utilisé pour stocker les données fréquemment utilisées et certaines données statiques dans le cache et les utiliser et les réserver selon les besoins de l'utilisateur.
  • Il existe de nombreuses structures de données présentes dans Redis que nous pouvons utiliser comme List, Set, Hashing, Stream et bien d'autres pour stocker les données.

Installation du cache Redis

Étape 1

Téléchargez le serveur Redis à l'aide de l'URL suivante

https://github.com/microsoftarchive/redis/releases/tag/win-3.0.504

Étape 2

Extrayez le fichier zip et ouvrez plus tard le serveur Redis et la CLI Redis

Implémentation de Redis Cache à l'aide de l'API .NET Core

Étape 1

Créer l'application Web de l'API .NET Core

Étape 2

Installez les packages NuGet suivants qui nécessitent étape par étape dans notre application

  • Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.DesignMicrosoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.SqlServerMicrosoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools
  • Swashbuckle.AspNetCore
  • StackExchange.Redis

Étape 3

Créez le dossier Modèle et créez une classe de produits à l'intérieur avec des détails

namespace RedisCacheDemo.Model
{
    public class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public string ProductDescription { get; set; }
        public int Stock { get; set; }
    }
}

Étape 4

Ensuite, créez la classe DbContextClass pour les opérations liées à la base de données comme je l'ai montré ci-dessous

using Microsoft.EntityFrameworkCore;
using RedisCacheDemo.Model;
namespace RedisCacheDemo.Data {
    public class DbContextClass: DbContext {
        public DbContextClass(DbContextOptions < DbContextClass > options): base(options) {}
        public DbSet < Product > Products {
            get;
            set;
        }
    }
}

Étape 5

Maintenant, nous allons créer l'interface ICacheService et la classe CacheService pour une utilisation liée au cache Redis.

using System;

namespace RedisCacheDemo.Cache
{
    public interface ICacheService
    {
        /// <summary>
        /// Get Data using key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        T GetData<T>(string key);

        /// <summary>
        /// Set Data with Value and Expiration Time of Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationTime"></param>
        /// <returns></returns>
        bool SetData<T>(string key, T value, DateTimeOffset expirationTime);

        /// <summary>
        /// Remove Data
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        object RemoveData(string key);
    }
}
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
namespace RedisCacheDemo.Cache {
    public class CacheService: ICacheService {
        private IDatabase _db;
        public CacheService() {
            ConfigureRedis();
        }
        private void ConfigureRedis() {
            _db = ConnectionHelper.Connection.GetDatabase();
        }
        public T GetData < T > (string key) {
            var value = _db.StringGet(key);
            if (!string.IsNullOrEmpty(value)) {
                return JsonConvert.DeserializeObject < T > (value);
            }
            return default;
        }
        public bool SetData < T > (string key, T value, DateTimeOffset expirationTime) {
            TimeSpan expiryTime = expirationTime.DateTime.Subtract(DateTime.Now);
            var isSet = _db.StringSet(key, JsonConvert.SerializeObject(value), expiryTime);
            return isSet;
        }
        public object RemoveData(string key) {
            bool _isKeyExist = _db.KeyExists(key);
            if (_isKeyExist == true) {
                return _db.KeyDelete(key);
            }
            return false;
        }
    }
}

Étape 6

Créez la classe ProductController et créez la méthode suivante comme indiqué ci-dessous

using Microsoft.AspNetCore.Mvc;
using RedisCacheDemo.Cache;
using RedisCacheDemo.Data;
using RedisCacheDemo.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RedisCacheDemo.Controllers {
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController: ControllerBase {
        private readonly DbContextClass _dbContext;
        private readonly ICacheService _cacheService;
        public ProductController(DbContextClass dbContext, ICacheService cacheService) {
                _dbContext = dbContext;
                _cacheService = cacheService;
            }
            [HttpGet("products")]
        public IEnumerable < Product > Get() {
                var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");
                if (cacheData != null) {
                    return cacheData;
                }
                var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);
                cacheData = _dbContext.Products.ToList();
                _cacheService.SetData < IEnumerable < Product >> ("product", cacheData, expirationTime);
                return cacheData;
            }
            [HttpGet("product")]
        public Product Get(int id) {
                Product filteredData;
                var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");
                if (cacheData != null) {
                    filteredData = cacheData.Where(x => x.ProductId == id).FirstOrDefault();
                    return filteredData;
                }
                filteredData = _dbContext.Products.Where(x => x.ProductId == id).FirstOrDefault();
                return filteredData;
            }
            [HttpPost("addproduct")]
        public async Task < Product > Post(Product value) {
                var obj = await _dbContext.Products.AddAsync(value);
                _cacheService.RemoveData("product");
                _dbContext.SaveChanges();
                return obj.Entity;
            }
            [HttpPut("updateproduct")]
        public void Put(Product product) {
                _dbContext.Products.Update(product);
                _cacheService.RemoveData("product");
                _dbContext.SaveChanges();
            }
            [HttpDelete("deleteproduct")]
        public void Delete(int Id) {
            var filteredData = _dbContext.Products.Where(x => x.ProductId == Id).FirstOrDefault();
            _dbContext.Remove(filteredData);
            _cacheService.RemoveData("product");
            _dbContext.SaveChanges();
        }
    }
}

Étape 7

Ajoutez la chaîne de connexion SQL Server et l'URL Redis dans appsetting.json

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*",
    "RedisURL": "127.0.0.1:6379",
    "ConnectionStrings": {
        "DefaultConnection": "Data Source=Server;Initial Catalog=RedisCache;User Id=sa;Password=***;"
    }
}

Étape 8

Ensuite, enregistrez ICacheService dans la méthode Configure Service de Startup Class et ajoutez également une configuration liée à Swagger pour tester nos points de terminaison API.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using RedisCacheDemo.Cache;
using RedisCacheDemo.Data;
namespace RedisCacheDemo {
    public class Startup {
        public Startup(IConfiguration configuration) {
            Configuration = configuration;
        }
        public IConfiguration Configuration {
            get;
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services) {
            services.AddControllers();
            services.AddScoped < ICacheService, CacheService > ();
            services.AddDbContext < DbContextClass > (options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            services.AddSwaggerGen(c => {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "RedisCacheDemo", Version = "v1"
                });
            });
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "RedisCacheDemo v1"));
            }
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
            });
        }
    }
}

Étape 9

Créez une classe ConfigurationManger pour configurer les paramètres de l'application là-bas

using Microsoft.Extensions.Configuration;
using System.IO;
namespace RedisCacheDemo {
    static class ConfigurationManager {
        public static IConfiguration AppSetting {
            get;
        }
        static ConfigurationManager() {
            AppSetting = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").Build();
        }
    }
}

Étape 10

Ensuite, créez une classe d'assistance de connexion pour la connexion Redis 

using StackExchange.Redis;
using System;
namespace RedisCacheDemo.Cache {
    public class ConnectionHelper {
        static ConnectionHelper() {
            ConnectionHelper.lazyConnection = new Lazy < ConnectionMultiplexer > (() => {
                return ConnectionMultiplexer.Connect(ConfigurationManager.AppSetting["RedisURL"]);
            });
        }
        private static Lazy < ConnectionMultiplexer > lazyConnection;
        public static ConnectionMultiplexer Connection {
            get {
                return lazyConnection.Value;
            }
        }
    }
}

Étape 11

Effectuez la migration et la mise à jour de la base de données pour la création de la base de données à l'aide des commandes suivantes dans la console du gestionnaire de packages.

add-migration "FirstMigration"
mise à jour de la base de données

Ainsi, lorsque vous entrez et exécutez cette commande, elle génère quelques éléments liés à la migration et crée la base de données dans SQL Server lorsque vous placez la chaîne de connexion dans le fichier appsetting.json.

Étape 12

Enfin, exécutez l'application et ajoutez les données à l'aide de l'interface utilisateur swagger, puis vérifiez le fonctionnement de la mise en cache dans les produits et le point de terminaison du produit.

Fondamentalement, j'ai ajouté du cache dans les points de terminaison du produit et des produits dans le contrôleur, comme vous le voyez lorsque l'utilisateur veut récupérer les données de tous les produits, il vérifiera d'abord si les données sont présentes dans le cache Redis ou non et si elles sont présentes dans le cache renvoie ensuite ces données à l'utilisateur et si les données ne sont pas présentes dans le cache, il récupère les données de la base de données et les place également dans le cache. Ainsi, la prochaine fois, l'utilisateur obtiendra cela uniquement à partir du cache et évitera d'accéder inutilement à la base de données

De plus, lorsque l'utilisateur souhaite récupérer des données à l'aide de l'identifiant du produit, comme vous le voyez dans le contrôleur du deuxième point de terminaison du produit, nous récupérons les données du cache de tous les produits, puis les filtrons à l'aide de l'identifiant du produit et, si cela se présente, revenons à l'utilisateur à partir du cache et pas ensuite récupérer de la base de données et revenir à l'utilisateur après avoir appliqué le filtre.

Ainsi, comme vous le voyez à l'intérieur de la mise à jour, de la suppression et de la publication du point de terminaison du contrôleur de produit, nous utilisons la méthode de suppression pour supprimer les données de la clé de produit qui sont présentes dans le cache. Ainsi, il existe de nombreux scénarios et utilisations de caches mémoire que vous pouvez utiliser selon vos besoins et vos exigences. Je veux juste présenter les bases du cache Redis et son fonctionnement à l'intérieur du .NET Core que j'ai couvert ici.

En outre, vous devez prendre en compte un scénario lors de l'utilisation de la mise en cache. Supposons que deux utilisateurs utilisent votre application, les scénarios suivants se produiront.

  • Lorsque le premier utilisateur envoie la demande pour récupérer les données de tous les produits, la première demande arrive, puis il vérifiera si les données sont présentes dans le cache ou non et si les données sont présentes dans le cache, il récupérera les données. à partir de la base de données et définissez-le également dans le cache.
  • Pendant ce temps, le deuxième utilisateur envoie la demande pour obtenir les détails du produit, puis ce qui s'est passé, c'est que cette demande atteint également la base de données avant de terminer la demande du premier utilisateur et, à cause de ce deuxième utilisateur, a également accédé à la base de données pour récupérer les détails du produit.
  • Donc, il existe une solution pour cela d'utiliser le mécanisme de verrouillage comme indiqué ci-dessous

Créez cet objet privé de verrou au-dessus de la classe

private static object _lock = new object()

Ensuite, modifiez la méthode Get comme je l'ai montré ci-dessous

public IEnumerable < Product > Get() {
    var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");
    if (cacheData != null) {
        return cacheData;
    }
    lock(_lock) {
        var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);
        cacheData = _dbContext.Products.ToList();
        _cacheService.SetData < IEnumerable < Product >> ("product", cacheData, expirationTime);
    }
    return cacheData;
}

Donc, ici, comme vous le voyez, nous vérifions d'abord si les données sont présentes dans le cache ou non si les données sont disponibles, puis nous les renvoyons. Ensuite, si la valeur n'est pas présente dans le cache Redis, nous appliquons le verrou là-bas, puis la demande est verrouillée et entrée dans la section et récupère les détails du produit dans la base de données, puis la définit également dans le cache, puis retourner les données. Alors, que s'est-il passé lorsque le deuxième utilisateur envoie une demande avant que la demande de l'utilisateur ne soit terminée. Ainsi, dans ce cas, la deuxième demande est dans la file d'attente et après avoir terminé la première demande de l'utilisateur, la deuxième demande entre en scène

En outre, vous pouvez voir les détails clés déjà présents dans Redis à l'aide de la CLI Redis, comme indiqué ci-dessous.

Donc, ici, vous pouvez voir qu'il existe de nombreuses commandes qui nous fournissent des informations sur les clés présentes dans le cache Redis.

Il s'agit du cache Redis dans .NET Core. J'espère que vous comprenez les choses liées à cela.

Bon codage !

Source : https://www.c-sharpcorner.com/article/implementation-of-the-redis-cache-in-the-net-core-api/

 #redis #dotnet #api 

Implémentation du Cache Redis dans l'API .NET Core
Trung  Nguyen

Trung Nguyen

1655929440

Triển khai Redis Cache trong .NET Core API

Chúng ta sẽ thảo luận về bộ nhớ đệm trong .NET Core và cách thức hoạt động của nó. Vì vậy, chúng ta xem xét từng thứ sau đây.

  • Giới thiệu về bộ nhớ đệm
  • Cache là gì
  • Các loại bộ nhớ đệm
  • Triển khai bộ nhớ đệm

Vì vậy, chúng ta hãy bắt đầu từng cái một.

Giới thiệu

Bộ nhớ đệm ngày nay rất phổ biến trong ngành công nghiệp phần mềm vì nó sẽ cải thiện hiệu suất và khả năng mở rộng của ứng dụng. Chúng tôi sử dụng nhiều ứng dụng web như Gmail và Facebook và xem chúng phản hồi như thế nào và chúng tôi có trải nghiệm người dùng tuyệt vời. Có rất nhiều người dùng sử dụng Internet và nếu một ứng dụng có nhu cầu và lưu lượng mạng lớn, chúng ta cần quan tâm đến nhiều thứ để giúp chúng ta cải thiện hiệu suất và khả năng phản hồi của ứng dụng. Vì vậy, do đó, có giải pháp bộ nhớ đệm và đó là lý do tại sao bộ nhớ đệm xuất hiện trong bức tranh.

Bộ nhớ đệm là gì?

Bộ nhớ đệm là bộ nhớ lưu trữ được sử dụng để lưu trữ dữ liệu truy cập thường xuyên vào bộ lưu trữ tạm thời, nó sẽ cải thiện hiệu suất đáng kể và tránh bị tấn công cơ sở dữ liệu không cần thiết và lưu trữ dữ liệu thường xuyên sử dụng vào bộ đệm bất cứ khi nào chúng ta cần.

Như bạn thấy trong hình trên, có hai trường hợp, một là không sử dụng bộ nhớ cache và một trường hợp khác là với bộ nhớ cache. Vì vậy, ở đây khi chúng ta không sử dụng bộ nhớ cache, trong trường hợp đó, giả sử người dùng muốn có dữ liệu thì họ sẽ truy cập vào cơ sở dữ liệu mỗi lần và nó sẽ làm tăng độ phức tạp về thời gian và giảm hiệu suất trong trường hợp có một số dữ liệu tĩnh mà người dùng muốn và điều đó cũng tương tự đối với tất cả người sử dụng. Trong trường hợp đó khi chúng ta không sử dụng bộ nhớ cache thì mỗi cái sẽ truy cập vào cơ sở dữ liệu không cần thiết để tìm nạp dữ liệu. Ở mặt khác, như bạn có thể thấy, chúng tôi sử dụng bộ nhớ cache và trong trường hợp đó nếu có cùng một dữ liệu tĩnh và cùng một dữ liệu cho tất cả người dùng thì chỉ người dùng đầu tiên sẽ truy cập cơ sở dữ liệu và tìm nạp dữ liệu và lưu trữ vào bộ nhớ đệm và sau đó hai người dùng khác đã sử dụng nó từ bộ nhớ cache mà không cần nhấn cơ sở dữ liệu một cách không cần thiết để tìm nạp dữ liệu.

Các loại bộ nhớ đệm

Về cơ bản, có hai loại bộ nhớ đệm .NET Core hỗ trợ

  1. Bộ nhớ đệm trong bộ nhớ
  2. Bộ nhớ đệm phân tán

Khi chúng tôi sử dụng In-Memory Cache thì trong trường hợp đó, dữ liệu được lưu trữ trong bộ nhớ của máy chủ ứng dụng và bất cứ khi nào chúng tôi cần thì chúng tôi tìm nạp dữ liệu từ đó và sử dụng nó ở bất cứ đâu chúng tôi cần. Và trong Bộ đệm ẩn phân tán có nhiều cơ chế của bên thứ ba như Redis và nhiều cơ chế khác. Nhưng trong phần này, chúng ta xem xét chi tiết Redis Cache và cách nó hoạt động trong .NET Core

Bộ nhớ đệm phân tán

  • Về cơ bản, trong cachin phân tán, dữ liệu g được lưu trữ và chia sẻ giữa nhiều máy chủ
  • Ngoài ra, thật dễ dàng để cải thiện khả năng mở rộng và hiệu suất của ứng dụng sau khi quản lý tải giữa nhiều máy chủ khi chúng tôi sử dụng ứng dụng nhiều người thuê
  • Giả sử, trong tương lai, nếu một máy chủ bị sự cố và khởi động lại thì ứng dụng không có bất kỳ tác động nào vì nhiều máy chủ là tùy theo nhu cầu của chúng tôi nếu chúng tôi muốn

Redis là bộ nhớ đệm phổ biến nhất được nhiều công ty sử dụng hiện nay để cải thiện hiệu suất và khả năng mở rộng của ứng dụng. Vì vậy, chúng ta sẽ thảo luận về Redis và cách sử dụng từng cái một.

Redis Cache

  • Redis là một kho lưu trữ Cấu trúc Dữ liệu trong Bộ nhớ Nguồn Mở (Được cấp phép BSD) được sử dụng làm cơ sở dữ liệu.
  • Về cơ bản, nó được sử dụng để lưu trữ dữ liệu thường được sử dụng và một số dữ liệu tĩnh bên trong bộ đệm và sử dụng và dự trữ theo yêu cầu của người dùng.
  • Có nhiều cấu trúc dữ liệu hiện diện trong Redis mà chúng ta có thể sử dụng như Danh sách, Đặt, Hashing, Luồng và nhiều cấu trúc khác để lưu trữ dữ liệu.

Cài đặt Redis Cache

Bước 1

Tải xuống Máy chủ Redis bằng URL sau

https://github.com/microsoftarchive/redis/releases/tag/win-3.0.504

Bước 2

Giải nén tệp zip và sau đó mở Redis Server và Redis CLI

Triển khai Redis Cache bằng .NET Core API

Bước 1

Tạo ứng dụng web .NET Core API

Bước 2

Cài đặt các Gói NuGet sau đây cần từng bước trong ứng dụng của chúng tôi

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools
  • Swashbuckle.AspNetCore
  • StackExchange.Redis

Bước 3

Tạo thư mục Model và tạo một Lớp Sản phẩm bên trong với các chi tiết

namespace RedisCacheDemo.Model
{
    public class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public string ProductDescription { get; set; }
        public int Stock { get; set; }
    }
}

Bước 4

Tiếp theo, Tạo Lớp DbContextClass cho các hoạt động liên quan đến Cơ sở dữ liệu như tôi đã trình bày bên dưới

using Microsoft.EntityFrameworkCore;
using RedisCacheDemo.Model;
namespace RedisCacheDemo.Data {
    public class DbContextClass: DbContext {
        public DbContextClass(DbContextOptions < DbContextClass > options): base(options) {}
        public DbSet < Product > Products {
            get;
            set;
        }
    }
}

Bước 5

Bây giờ, chúng ta sẽ tạo Giao diện ICacheService và Lớp CacheService để sử dụng liên quan đến Redis Cache.

using System;

namespace RedisCacheDemo.Cache
{
    public interface ICacheService
    {
        /// <summary>
        /// Get Data using key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        T GetData<T>(string key);

        /// <summary>
        /// Set Data with Value and Expiration Time of Key
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationTime"></param>
        /// <returns></returns>
        bool SetData<T>(string key, T value, DateTimeOffset expirationTime);

        /// <summary>
        /// Remove Data
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        object RemoveData(string key);
    }
}
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
namespace RedisCacheDemo.Cache {
    public class CacheService: ICacheService {
        private IDatabase _db;
        public CacheService() {
            ConfigureRedis();
        }
        private void ConfigureRedis() {
            _db = ConnectionHelper.Connection.GetDatabase();
        }
        public T GetData < T > (string key) {
            var value = _db.StringGet(key);
            if (!string.IsNullOrEmpty(value)) {
                return JsonConvert.DeserializeObject < T > (value);
            }
            return default;
        }
        public bool SetData < T > (string key, T value, DateTimeOffset expirationTime) {
            TimeSpan expiryTime = expirationTime.DateTime.Subtract(DateTime.Now);
            var isSet = _db.StringSet(key, JsonConvert.SerializeObject(value), expiryTime);
            return isSet;
        }
        public object RemoveData(string key) {
            bool _isKeyExist = _db.KeyExists(key);
            if (_isKeyExist == true) {
                return _db.KeyDelete(key);
            }
            return false;
        }
    }
}

Bước 6

Tạo lớp ProductController và tạo phương thức sau như hình dưới đây

using Microsoft.AspNetCore.Mvc;
using RedisCacheDemo.Cache;
using RedisCacheDemo.Data;
using RedisCacheDemo.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RedisCacheDemo.Controllers {
    [Route("api/[controller]")]
    [ApiController]
    public class ProductController: ControllerBase {
        private readonly DbContextClass _dbContext;
        private readonly ICacheService _cacheService;
        public ProductController(DbContextClass dbContext, ICacheService cacheService) {
                _dbContext = dbContext;
                _cacheService = cacheService;
            }
            [HttpGet("products")]
        public IEnumerable < Product > Get() {
                var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");
                if (cacheData != null) {
                    return cacheData;
                }
                var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);
                cacheData = _dbContext.Products.ToList();
                _cacheService.SetData < IEnumerable < Product >> ("product", cacheData, expirationTime);
                return cacheData;
            }
            [HttpGet("product")]
        public Product Get(int id) {
                Product filteredData;
                var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");
                if (cacheData != null) {
                    filteredData = cacheData.Where(x => x.ProductId == id).FirstOrDefault();
                    return filteredData;
                }
                filteredData = _dbContext.Products.Where(x => x.ProductId == id).FirstOrDefault();
                return filteredData;
            }
            [HttpPost("addproduct")]
        public async Task < Product > Post(Product value) {
                var obj = await _dbContext.Products.AddAsync(value);
                _cacheService.RemoveData("product");
                _dbContext.SaveChanges();
                return obj.Entity;
            }
            [HttpPut("updateproduct")]
        public void Put(Product product) {
                _dbContext.Products.Update(product);
                _cacheService.RemoveData("product");
                _dbContext.SaveChanges();
            }
            [HttpDelete("deleteproduct")]
        public void Delete(int Id) {
            var filteredData = _dbContext.Products.Where(x => x.ProductId == Id).FirstOrDefault();
            _dbContext.Remove(filteredData);
            _cacheService.RemoveData("product");
            _dbContext.SaveChanges();
        }
    }
}

Bước 7

Thêm chuỗi kết nối SQL Server và URL Redis bên trong appsetting.json

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*",
    "RedisURL": "127.0.0.1:6379",
    "ConnectionStrings": {
        "DefaultConnection": "Data Source=Server;Initial Catalog=RedisCache;User Id=sa;Password=***;"
    }
}

Bước 8

Tiếp theo, Đăng ký ICacheService bên trong phương thức Cấu hình Dịch vụ của Lớp Khởi động và cũng thêm một số cấu hình liên quan đến Swagger để kiểm tra các điểm cuối API của chúng tôi

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using RedisCacheDemo.Cache;
using RedisCacheDemo.Data;
namespace RedisCacheDemo {
    public class Startup {
        public Startup(IConfiguration configuration) {
            Configuration = configuration;
        }
        public IConfiguration Configuration {
            get;
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services) {
            services.AddControllers();
            services.AddScoped < ICacheService, CacheService > ();
            services.AddDbContext < DbContextClass > (options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            services.AddSwaggerGen(c => {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "RedisCacheDemo", Version = "v1"
                });
            });
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "RedisCacheDemo v1"));
            }
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
            });
        }
    }
}

Bước 9

Tạo một lớp ConfigurationManger để định cấu hình cài đặt ứng dụng ở đó

using Microsoft.Extensions.Configuration;
using System.IO;
namespace RedisCacheDemo {
    static class ConfigurationManager {
        public static IConfiguration AppSetting {
            get;
        }
        static ConfigurationManager() {
            AppSetting = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").Build();
        }
    }
}

Bước 10

Tiếp theo, Tạo lớp trợ giúp kết nối cho Redis Connection 

using StackExchange.Redis;
using System;
namespace RedisCacheDemo.Cache {
    public class ConnectionHelper {
        static ConnectionHelper() {
            ConnectionHelper.lazyConnection = new Lazy < ConnectionMultiplexer > (() => {
                return ConnectionMultiplexer.Connect(ConfigurationManager.AppSetting["RedisURL"]);
            });
        }
        private static Lazy < ConnectionMultiplexer > lazyConnection;
        public static ConnectionMultiplexer Connection {
            get {
                return lazyConnection.Value;
            }
        }
    }
}

Bước 11

Thực hiện Di chuyển và Cập nhật Cơ sở dữ liệu cho Tạo DB bằng các lệnh sau trong Bảng điều khiển Trình quản lý Gói.

cơ sở dữ liệu cập nhật bổ sung "FirstMigration"
 

Vì vậy, khi bạn nhập và thực thi lệnh này, nó sẽ tạo ra một số thứ liên quan đến việc di chuyển và tạo cơ sở dữ liệu bên trong SQL Server khi bạn đặt bên trong Chuỗi kết nối trong appsetting.json

Bước 12

Cuối cùng, chạy ứng dụng và thêm dữ liệu bằng giao diện người dùng swagger và sau đó kiểm tra cách bộ nhớ đệm hoạt động bên trong sản phẩm và điểm cuối của sản phẩm.

Về cơ bản, tôi đã thêm bộ nhớ cache vào sản phẩm và các điểm cuối của sản phẩm trong bộ điều khiển, như bạn thấy khi người dùng muốn tìm nạp dữ liệu của tất cả các sản phẩm thì trước tiên, nó sẽ kiểm tra xem dữ liệu có bên trong Redis Cache hay không và nếu nó có bên trong sau đó bộ nhớ đệm trả lại dữ liệu đó cho người dùng và nếu dữ liệu không có bên trong bộ đệm, thì nó sẽ tìm nạp dữ liệu từ cơ sở dữ liệu và đồng thời, đặt dữ liệu đó vào bộ đệm. Vì vậy, lần sau người dùng sẽ chỉ nhận được điều đó từ bộ nhớ cache và tránh đánh vào cơ sở dữ liệu một cách không cần thiết

Ngoài ra, khi người dùng muốn tìm nạp dữ liệu từ bằng cách sử dụng id sản phẩm như bạn thấy trong bộ điều khiển ở điểm cuối thứ hai của sản phẩm, chúng tôi tìm nạp dữ liệu từ bộ nhớ cache của tất cả các sản phẩm, sau đó lọc bằng id sản phẩm và nếu điều đó xuất hiện thì trả về cho người dùng từ bộ nhớ cache và sau đó không tìm nạp từ cơ sở dữ liệu và trở lại người dùng sau khi áp dụng bộ lọc.

Vì vậy, như bạn thấy bên trong cập nhật, xóa và đăng điểm cuối của Bộ điều khiển sản phẩm, sau đó chúng tôi sử dụng phương pháp loại bỏ để xóa dữ liệu của khóa sản phẩm có bên trong bộ nhớ cache. Vì vậy, có rất nhiều tình huống và cách sử dụng bộ nhớ đệm mà bạn có thể sử dụng tùy theo nhu cầu và yêu cầu của mình. Tôi chỉ muốn giới thiệu những điều cơ bản về Redis Cache và cách nó hoạt động bên trong .NET Core mà tôi đã trình bày ở đây.

Ngoài ra, có một trường hợp bạn cần lưu ý khi sử dụng bộ nhớ đệm. Giả sử có hai người dùng sử dụng ứng dụng của bạn thì các trường hợp sau sẽ xảy ra.

  • Khi Người dùng thứ nhất gửi yêu cầu tìm nạp dữ liệu của tất cả các sản phẩm thì yêu cầu đầu tiên sẽ đến và sau đó nó sẽ kiểm tra xem dữ liệu có bên trong bộ đệm hay không và nếu dữ liệu có bên trong bộ đệm, thì nó sẽ tìm nạp dữ liệu từ và cơ sở dữ liệu và cũng đặt nó vào bộ nhớ cache.
  • Trong khi đó, Người dùng thứ hai gửi yêu cầu để lấy chi tiết sản phẩm thì điều đã xảy ra là yêu cầu đó cũng truy cập vào cơ sở dữ liệu trước khi hoàn thành yêu cầu của người dùng thứ nhất và vì người dùng thứ hai đó cũng truy cập vào cơ sở dữ liệu để lấy chi tiết sản phẩm.
  • Vì vậy, có một giải pháp cho việc này là sử dụng Cơ chế khóa như hình dưới đây

Tạo đối tượng khóa riêng tư này trên đầu lớp

private static object _lock = new object()

Tiếp theo, sửa đổi phương thức Get như tôi đã hiển thị bên dưới

public IEnumerable < Product > Get() {
    var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");
    if (cacheData != null) {
        return cacheData;
    }
    lock(_lock) {
        var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);
        cacheData = _dbContext.Products.ToList();
        _cacheService.SetData < IEnumerable < Product >> ("product", cacheData, expirationTime);
    }
    return cacheData;
}

Vì vậy, ở đây như bạn thấy, trước tiên, chúng tôi kiểm tra xem dữ liệu có bên trong bộ đệm hay không nếu dữ liệu có sẵn thì trả về. Tiếp theo, nếu giá trị không có trong bộ nhớ cache của Redis, thì chúng tôi áp dụng khóa ở đó và sau đó yêu cầu được khóa và nhập vào phần và tìm nạp chi tiết sản phẩm từ cơ sở dữ liệu, sau đó cũng đặt nó vào bộ nhớ cache và sau đó trả lại dữ liệu. Vì vậy, điều gì đã xảy ra khi người dùng thứ hai gửi yêu cầu trước khi yêu cầu của người dùng đó hoàn tất. Vì vậy, trong trường hợp đó, yêu cầu thứ hai nằm trong hàng đợi và sau khi hoàn thành yêu cầu người dùng đầu tiên, yêu cầu thứ hai xuất hiện trong hình

Ngoài ra, bạn có thể xem các chi tiết chính đã có bên trong Redis bằng Redis CLI như hình dưới đây

Vì vậy, ở đây bạn có thể thấy có nhiều lệnh cung cấp cho chúng tôi thông tin về các khóa có trong Redis Cache.

Đây là tất cả về Redis Cache trong .NET Core. Tôi hy vọng bạn hiểu những điều liên quan đến điều đó.

Chúc bạn mã hóa vui vẻ!

Nguồn: https://www.c-sharpcorner.com/article/implementation-of-the-redis-cache-in-the-net-core-api/

 #redis #dotnet #api 

Triển khai Redis Cache trong .NET Core API

Implementação Do Cache Redis Na API Do .NET Core

Vamos discutir o cache no .NET Core e como ele funciona. Então, vamos olhar para as seguintes coisas, uma por uma.

  • Introdução ao cache
  • O que é Cache
  • Tipos de cache
  • Implementação de cache

Então, vamos começar um por um.

Introdução

O armazenamento em cache é muito popular hoje em dia na indústria de software porque melhorará o desempenho e a escalabilidade do aplicativo. Usamos muitos aplicativos da web como Gmail e Facebook e vemos como eles são responsivos e temos uma ótima experiência do usuário. Há muitos usuários usando a internet e se um aplicativo tem grande tráfego de rede e demanda, precisamos cuidar de muitas coisas que nos ajudam a melhorar o desempenho e a capacidade de resposta do aplicativo. Então, por causa disso, existe a solução do cache e é por isso que o cache entra em cena.

O que é cache?

O cache é o armazenamento de memória que é usado para armazenar os dados de acesso frequente no armazenamento temporário, melhorará drasticamente o desempenho e evitará o acesso desnecessário ao banco de dados e armazenará dados usados ​​com frequência no buffer sempre que precisarmos.

Como você vê na imagem acima existem dois cenários, um é sem usar cache e outro é com cache. Então, aqui, quando não usamos o cache, nesse caso, suponha que os usuários desejam dados, eles acessarão cada vez o banco de dados e aumentará a complexidade do tempo e reduzirá o desempenho caso haja alguns dados estáticos que os usuários desejam e é o mesmo para todos os usuários. Nesse caso, quando não usamos o cache, cada um acessa o banco de dados desnecessário para buscar dados. Por outro lado, como você pode ver, usamos cache e, nesse caso, se houver a mesma estática e os mesmos dados para todos os usuários, apenas o primeiro usuário acessará o banco de dados e buscará os dados e os armazenará na memória cache e, em seguida, outros dois usuários usaram isso do cache sem acessar desnecessariamente o banco de dados para buscar dados.

Tipos de cache

Basicamente, existem dois tipos de suporte a cache do .NET Core

  1. Cache na memória
  2. Cache distribuído

Quando usamos o In-Memory Cache, nesse caso, os dados são armazenados na memória do servidor de aplicativos e, sempre que precisamos, buscamos os dados e os usamos onde quer que precisemos. E no Distributed Caching existem muitos mecanismos de terceiros como Redis e muitos outros. Mas nesta seção, examinamos o Cache Redis em detalhes e como ele funciona no .NET Core

Cache distribuído

  • Basicamente, no cache distribuído, os dados são armazenados e compartilhados entre vários servidores
  • Além disso, é fácil melhorar a escalabilidade e o desempenho do aplicativo depois de gerenciar a carga entre vários servidores quando usamos o aplicativo multilocatário
  • Suponha que, no futuro, se um servidor for travado e reiniciado, o aplicativo não terá nenhum impacto porque vários servidores são conforme nossa necessidade, se quisermos

Redis é o cache mais popular usado por muitas empresas hoje em dia para melhorar o desempenho e a escalabilidade do aplicativo. Então, vamos discutir o Redis e o uso um por um.

Cache Redis

  • Redis é um armazenamento de estrutura de dados em memória de código aberto (licenciado BSD) usado como banco de dados.
  • Basicamente, ele é usado para armazenar os dados usados ​​com frequência e alguns dados estáticos dentro do cache e usá-los e reservá-los conforme a necessidade do usuário.
  • Existem muitas estruturas de dados presentes no Redis que podemos usar, como List, Set, Hashing, Stream e muito mais para armazenar os dados.

Instalação do Redis Cache

Passo 1

Baixe o Redis Server usando o seguinte URL

https://github.com/microsoftarchive/redis/releases/tag/win-3.0.504

Passo 2

Extraia o arquivo zip e, posteriormente, abra o Redis Server e a Redis CLI

Implementação do Redis Cache usando a API do .NET Core

Passo 1

Criar o aplicativo Web da API do .NET Core

Passo 2

Instale os seguintes pacotes NuGet que precisam passo a passo em nosso aplicativo

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools
  • Swashbuckle.AspNetCore
  • StackExchange.Redis

etapa 3

Crie a pasta Model e crie uma classe de produto dentro dela com detalhes

namespace RedisCacheDemo.Model{    public class Product    {        public int ProductId { get; set; }        public string ProductName { get; set; }        public string ProductDescription { get; set; }        public int Stock { get; set; }    }}

Passo 4

Em seguida, crie a classe DbContextClass para operações relacionadas ao banco de dados como mostrei abaixo

using Microsoft.EntityFrameworkCore;using RedisCacheDemo.Model;namespace RedisCacheDemo.Data {    public class DbContextClass: DbContext {        public DbContextClass(DbContextOptions < DbContextClass > options): base(options) {}        public DbSet < Product > Products {            get;            set;        }    }}

Etapa 5

Agora, vamos criar a Interface ICacheService e a Classe CacheService para uso relacionado ao Redis Cache.

using System;namespace RedisCacheDemo.Cache{    public interface ICacheService    {        /// <summary>        /// Get Data using key        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="key"></param>        /// <returns></returns>        T GetData<T>(string key);        /// <summary>        /// Set Data with Value and Expiration Time of Key        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="key"></param>        /// <param name="value"></param>        /// <param name="expirationTime"></param>        /// <returns></returns>        bool SetData<T>(string key, T value, DateTimeOffset expirationTime);        /// <summary>        /// Remove Data        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        object RemoveData(string key);    }}
using Newtonsoft.Json;using StackExchange.Redis;using System;namespace RedisCacheDemo.Cache {    public class CacheService: ICacheService {        private IDatabase _db;        public CacheService() {            ConfigureRedis();        }        private void ConfigureRedis() {            _db = ConnectionHelper.Connection.GetDatabase();        }        public T GetData < T > (string key) {            var value = _db.StringGet(key);            if (!string.IsNullOrEmpty(value)) {                return JsonConvert.DeserializeObject < T > (value);            }            return default;        }        public bool SetData < T > (string key, T value, DateTimeOffset expirationTime) {            TimeSpan expiryTime = expirationTime.DateTime.Subtract(DateTime.Now);            var isSet = _db.StringSet(key, JsonConvert.SerializeObject(value), expiryTime);            return isSet;        }        public object RemoveData(string key) {            bool _isKeyExist = _db.KeyExists(key);            if (_isKeyExist == true) {                return _db.KeyDelete(key);            }            return false;        }    }}

Etapa 6

Crie a classe ProductController e crie o seguinte método conforme mostrado abaixo

using Microsoft.AspNetCore.Mvc;using RedisCacheDemo.Cache;using RedisCacheDemo.Data;using RedisCacheDemo.Model;using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;namespace RedisCacheDemo.Controllers {    [Route("api/[controller]")]    [ApiController]    public class ProductController: ControllerBase {        private readonly DbContextClass _dbContext;        private readonly ICacheService _cacheService;        public ProductController(DbContextClass dbContext, ICacheService cacheService) {                _dbContext = dbContext;                _cacheService = cacheService;            }            [HttpGet("products")]        public IEnumerable < Product > Get() {                var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");                if (cacheData != null) {                    return cacheData;                }                var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);                cacheData = _dbContext.Products.ToList();                _cacheService.SetData < IEnumerable < Product >> ("product", cacheData, expirationTime);                return cacheData;            }            [HttpGet("product")]        public Product Get(int id) {                Product filteredData;                var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");                if (cacheData != null) {                    filteredData = cacheData.Where(x => x.ProductId == id).FirstOrDefault();                    return filteredData;                }                filteredData = _dbContext.Products.Where(x => x.ProductId == id).FirstOrDefault();                return filteredData;            }            [HttpPost("addproduct")]        public async Task < Product > Post(Product value) {                var obj = await _dbContext.Products.AddAsync(value);                _cacheService.RemoveData("product");                _dbContext.SaveChanges();                return obj.Entity;            }            [HttpPut("updateproduct")]        public void Put(Product product) {                _dbContext.Products.Update(product);                _cacheService.RemoveData("product");                _dbContext.SaveChanges();            }            [HttpDelete("deleteproduct")]        public void Delete(int Id) {            var filteredData = _dbContext.Products.Where(x => x.ProductId == Id).FirstOrDefault();            _dbContext.Remove(filteredData);            _cacheService.RemoveData("product");            _dbContext.SaveChanges();        }    }}

Etapa 7

Adicione a string de conexão do SQL Server e a URL do Redis dentro de appsetting.json

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*",
    "RedisURL": "127.0.0.1:6379",
    "ConnectionStrings": {
        "DefaultConnection": "Data Source=Server;Initial Catalog=RedisCache;User Id=sa;Password=***;"
    }
}

Etapa 8

Em seguida, registre o ICacheService dentro do método Configure Service da Startup Class e também adicione algumas configurações relacionadas ao Swagger para testar nossos endpoints da API

using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.EntityFrameworkCore;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using Microsoft.OpenApi.Models;using RedisCacheDemo.Cache;using RedisCacheDemo.Data;namespace RedisCacheDemo {    public class Startup {        public Startup(IConfiguration configuration) {            Configuration = configuration;        }        public IConfiguration Configuration {            get;        }        // This method gets called by the runtime. Use this method to add services to the container.        public void ConfigureServices(IServiceCollection services) {            services.AddControllers();            services.AddScoped < ICacheService, CacheService > ();            services.AddDbContext < DbContextClass > (options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));            services.AddSwaggerGen(c => {                c.SwaggerDoc("v1", new OpenApiInfo {                    Title = "RedisCacheDemo", Version = "v1"                });            });        }        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {            if (env.IsDevelopment()) {                app.UseDeveloperExceptionPage();                app.UseSwagger();                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "RedisCacheDemo v1"));            }            app.UseHttpsRedirection();            app.UseRouting();            app.UseAuthorization();            app.UseEndpoints(endpoints => {                endpoints.MapControllers();            });        }    }}

Etapa 9

Crie uma classe ConfigurationManger para definir a configuração do aplicativo por lá

using Microsoft.Extensions.Configuration;using System.IO;namespace RedisCacheDemo {    static class ConfigurationManager {        public static IConfiguration AppSetting {            get;        }        static ConfigurationManager() {            AppSetting = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").Build();        }    }}

Etapa 10

Em seguida, Criar classe auxiliar de conexão para conexão Redis 

using StackExchange.Redis;using System;namespace RedisCacheDemo.Cache {    public class ConnectionHelper {        static ConnectionHelper() {            ConnectionHelper.lazyConnection = new Lazy < ConnectionMultiplexer > (() => {                return ConnectionMultiplexer.Connect(ConfigurationManager.AppSetting["RedisURL"]);            });        }        private static Lazy < ConnectionMultiplexer > lazyConnection;        public static ConnectionMultiplexer Connection {            get {                return lazyConnection.Value;            }        }    }}

Etapa 11

Execute migração e atualização de banco de dados para criação de banco de dados usando os comandos a seguir no console do gerenciador de pacotes.

add-migration "FirstMigration"
update-database

Portanto, quando você inserir e executar este comando, ele gerará algumas coisas relacionadas à migração e criará o banco de dados dentro do SQL Server conforme você coloca dentro da Connection String no appsetting.json

Etapa 12

Por fim, execute o aplicativo e adicione os dados usando a interface do usuário do swagger e, em seguida, verifique como o armazenamento em cache funciona nos produtos e no endpoint do produto.

Basicamente, adicionei cache nos endpoints do produto e produtos no controlador, como você vê quando o usuário deseja buscar dados de todos os produtos, primeiro ele verificará se os dados estão presentes dentro do Redis Cache ou não e se estão presentes dentro do cache, em seguida, retorna esses dados para o usuário e, se os dados não estiverem presentes dentro do cache, ele buscará os dados do banco de dados e também os definirá no cache. Então, da próxima vez, o usuário obterá isso apenas do cache e evitará acessar o banco de dados desnecessariamente

Além disso, quando o usuário deseja buscar dados usando o ID do produto como você vê no controlador no segundo endpoint do produto, buscamos dados do cache de todos os produtos e filtramos usando o ID do produto e, se isso for apresentado, retornamos ao usuário do cache e não buscar no banco de dados e retornar ao usuário após aplicar o filtro.

Então, como você vê dentro de update, delete e post endpoint do Product Controller, então usamos o método remove para remover os dados da chave do produto que está presente dentro do cache. Portanto, existem muitos cenários e uso de caches de memória que você pode usar de acordo com sua necessidade e requisitos. Eu só quero apresentar o básico do Redis Cache e como ele funciona dentro do .NET Core que abordei aqui.

Além disso, há um cenário que você precisa cuidar ao usar o cache. Suponha que haja dois usuários usando seu aplicativo, então os seguintes cenários acontecerão.

  • Quando o Primeiro Usuário envia a requisição para buscar os dados de todos os produtos então vem a primeira requisição e então ele vai checar se os dados estão presentes dentro do cache ou não e se os dados estão presentes dentro do cache, então ele vai buscar os dados de e banco de dados e também configurá-lo para o cache.
  • Enquanto isso, o segundo usuário envia a solicitação para obter os detalhes do produto, então o que aconteceu é que a solicitação também atinge o banco de dados antes de concluir a solicitação do primeiro usuário e, por causa desse segundo usuário, também acessa o banco de dados para buscar os detalhes do produto.
  • Portanto, existe uma solução para isso usar o mecanismo de bloqueio, conforme mostrado abaixo

Crie este objeto privado de bloqueio no topo da classe

private static object _lock = new object()

Em seguida, modifique o método Get como mostrei abaixo

public IEnumerable < Product > Get() {    var cacheData = _cacheService.GetData < IEnumerable < Product >> ("product");    if (cacheData != null) {        return cacheData;    }    lock(_lock) {        var expirationTime = DateTimeOffset.Now.AddMinutes(5.0);        cacheData = _dbContext.Products.ToList();        _cacheService.SetData < IEnumerable < Product >> ("product", cacheData, expirationTime);    }    return cacheData;}

Então aqui, como você vê, primeiro, verificamos se os dados estão presentes dentro do cache ou não, se os dados estão disponíveis, então retornamos isso. Em seguida, se o valor não estiver presente no cache do Redis, aplicamos o bloqueio ali e, em seguida, a solicitação é bloqueada e inserida na seção e buscamos os detalhes do produto no banco de dados, e também definimos para o cache e, em seguida, retornar os dados. Então, o que aconteceu quando o segundo usuário envia uma solicitação antes que a solicitação do usuário seja concluída. Então, nesse caso, a segunda solicitação está na fila e depois de concluir a primeira solicitação do usuário, a segunda solicitação entra em cena

Além disso, você pode ver os principais detalhes que já estão presentes no Redis usando o Redis CLI, conforme mostrado abaixo

Então, aqui você pode ver que existem muitos comandos que nos fornecem informações sobre as chaves que estão presentes no Redis Cache.

Isso é tudo sobre o Redis Cache no .NET Core. Espero que você entenda as coisas relacionadas a isso.

Boa Codificação!

Fonte: https://www.c-sharpcorner.com/article/implementation-of-the-redis-cache-in-the-net-core-api/

  #redis #dotnet #api 

Implementação Do Cache Redis Na API Do .NET Core