Доступ к удаленным даннымAccessing Remote Data

Многие современные решения на основе веб-сделать использование веб-служб, размещенных на веб-серверах, для предоставления функций для удаленных клиентских приложений.Many modern web-based solutions make use of web services, hosted by web servers, to provide functionality for remote client applications. Операции, которые веб-служба предоставляет составляют веб-API.The operations that a web service exposes constitute a web API.

Клиентские приложения, следует использовать веб-API, не зная, как реализованы данных или операций, которые предоставляет API.Client apps should be able to utilize the web API without knowing how the data or operations that the API exposes are implemented. Для этого требуется, что API соответствовать общепринятым стандартам, приложения и веб-служба клиента согласовать формат данных и структуры данных, которыми обмениваются клиентские приложения и веб-службы.This requires that the API abides by common standards that enable a client app and web service to agree on which data formats to use, and the structure of the data that is exchanged between client apps and the web service.

Общие сведения об архитектурных принципов Representational State TransferIntroduction to Representational State Transfer

Representational State Transfer (REST) представляет собой архитектурный стиль для построения распределенных систем, на основе гиперсред.Representational State Transfer (REST) is an architectural style for building distributed systems based on hypermedia. Основное преимущество модели REST является основана на открытых стандартах и не выполняет привязку реализации модели или клиентских приложений, использующих ее любой конкретной реализации.A primary advantage of the REST model is that it's based on open standards and doesn't bind the implementation of the model or the client apps that access it to any specific implementation. Таким образом веб-службы REST могут быть реализованы с помощью Microsoft ASP.NET Core MVC и клиентских приложений может разработки на любой язык и набор инструментов для создания HTTP-запросы и анализировать HTTP-ответы.Therefore, a REST web service could be implemented using Microsoft ASP.NET Core MVC, and client apps could be developing using any language and toolset that can generate HTTP requests and parse HTTP responses.

Модель REST использует схему переходов для представления объектов и служб в сети, называемые ресурсами.The REST model uses a navigational scheme to represent objects and services over a network, referred to as resources. Систем, которые обычно реализуют REST используется протокол HTTP для передачи запросов на доступ к этим ресурсам.Systems that implement REST typically use the HTTP protocol to transmit requests to access these resources. В таких системах клиентское приложение отправляет запрос в виде URI, идентифицирующий ресурс и метод HTTP (например, GET, POST, PUT или DELETE), указывающее операцию для выполнения на указанном ресурсе.In such systems, a client app submits a request in the form of a URI that identifies a resource, and an HTTP method (such as GET, POST, PUT, or DELETE) that indicates the operation to be performed on that resource. Текст HTTP-запроса содержит данные, которые требуются для выполнения операции.The body of the HTTP request contains any data required to perform the operation.

Примечание

REST определяет модель запроса без отслеживания состояния.REST defines a stateless request model. Таким образом HTTP-запросы должны быть независимыми и могут возникнуть в любом порядке.Therefore, HTTP requests must be independent and might occur in any order.

Ответ REST запроса позволяет использовать стандартные коды состояния HTTP.The response from a REST request makes use of standard HTTP status codes. Например запрос, возвращающий допустимые данные должны включать код ответа HTTP 200 (ОК), хотя запрос, который не удалось найти или удалить указанный ресурс должен вернуть ответ, который включает код состояния HTTP 404 (не найдено).For example, a request that returns valid data should include the HTTP response code 200 (OK), while a request that fails to find or delete a specified resource should return a response that includes the HTTP status code 404 (Not Found).

Веб-API RESTful определяет набор взаимосвязанных ресурсов и предоставляет основные операции, которые позволяют приложению управлять эти ресурсы и беспрепятственно перемещаться между ними.A RESTful web API exposes a set of connected resources, and provides the core operations that enable an app to manipulate those resources and easily navigate between them. По этой причине URI, которые составляют типичный веб-API RESTful ориентированы на данные, которые он предоставляет и использовать средства по HTTP для работы с этими данными.For this reason, the URIs that constitute a typical RESTful web API are oriented towards the data that it exposes, and use the facilities provided by HTTP to operate on this data.

Данные, включенные в HTTP-запроса и соответствующие ответные сообщения из веб-сервера, клиентского приложения можно представить в различных форматах, известные как типы мультимедиа.The data included by a client app in an HTTP request, and the corresponding response messages from the web server, could be presented in a variety of formats, known as media types. Когда клиентское приложение отправляет запрос, который возвращает данные в тексте сообщения, оно может указать типы мультимедиа, он может обрабатывать в Accept заголовок запроса.When a client app sends a request that returns data in the body of a message, it can specify the media types it can handle in the Accept header of the request. Если веб-сервер поддерживает этот тип носителя, он может вернуть ответ, включающий Content-Type заголовок, который указывает формат данных в теле сообщения.If the web server supports this media type, it can reply with a response that includes the Content-Type header that specifies the format of the data in the body of the message. Затем это ответственность за анализ ответного сообщения и интерпретировать результаты в теле сообщения соответствующим образом клиентское приложение.It's then the responsibility of the client app to parse the response message and interpret the results in the message body appropriately.

Дополнительные сведения о REST см. в разделе по проектированию API и реализации API.For more information about REST, see API design and API implementation.

Использование API-интерфейсов RESTfulConsuming RESTful APIs

Мобильное приложение eShopOnContainers использует шаблон Model-View-ViewModel (MVVM), а также элементы модели представляет шаблон сущности предметной области, используемые в приложении.The eShopOnContainers mobile app uses the Model-View-ViewModel (MVVM) pattern, and the model elements of the pattern represent the domain entities used in the app. Классы контроллера и репозитория в образце приложения eShopOnContainers принимать и возвращать многие из этих объектов модели.The controller and repository classes in the eShopOnContainers reference application accept and return many of these model objects. Таким образом они используются как объекты передачи данных (DTO), которые содержат все данные, передаваемые между мобильного приложения и контейнерные микрослужбы.Therefore, they are used as data transfer objects (DTOs) that hold all the data that is passed between the mobile app and the containerized microservices. Основным преимуществом использования DTO для передачи данных и получения данных из веб-службы является передача дополнительных данных в один удаленный вызов, приложение может сократить число удаленных вызовов, которые необходимо внести.The main benefit of using DTOs to pass data to and receive data from a web service is that by transmitting more data in a single remote call, the app can reduce the number of remote calls that need to be made.

Выполнение веб-запросовMaking Web Requests

Мобильное приложение eShopOnContainers использует HttpClient класса для выполнения запросов по протоколу HTTP с JSON, используемой в качестве типа носителя.The eShopOnContainers mobile app uses the HttpClient class to make requests over HTTP, with JSON being used as the media type. Этот класс предоставляет функциональные возможности для асинхронной отправки HTTP-запросов и получения HTTP-ответов из URI определен ресурс.This class provides functionality for asynchronously sending HTTP requests and receiving HTTP responses from a URI identified resource. HttpResponseMessage Класс представляет сообщение ответа HTTP, полученные от REST API, после HTTP-запроса.The HttpResponseMessage class represents an HTTP response message received from a REST API after an HTTP request has been made. Он содержит сведения об ответе, включая код состояния, заголовков и любой текст.It contains information about the response, including the status code, headers, and any body. HttpContent Класс представляет тело HTTP и заголовки содержимого, таких как Content-Type и Content-Encoding.The HttpContent class represents the HTTP body and content headers, such as Content-Type and Content-Encoding. Можно прочитать содержимое с помощью любого из ReadAs методы, такие как ReadAsStringAsync и ReadAsByteArrayAsync, в зависимости от формата данных.The content can be read using any of the ReadAs methods, such as ReadAsStringAsync and ReadAsByteArrayAsync, depending on the format of the data.

Запрос GETMaking a GET Request

CatalogService Класс используется для управления процессом получения данных из микрослужбы каталога.The CatalogService class is used to manage the data retrieval process from the catalog microservice. В RegisterDependencies метод в ViewModelLocator класс, CatalogService класс регистрируется как сопоставление типов для ICatalogService типа с помощью контейнера внедрения зависимостей Autofac.In the RegisterDependencies method in the ViewModelLocator class, the CatalogService class is registered as a type mapping against the ICatalogService type with the Autofac dependency injection container. Теперь, когда экземпляр CatalogViewModel создается класс, его конструктор принимает ICatalogService тип, который разрешает Autofac, возвращение экземпляра CatalogService класса.Then, when an instance of the CatalogViewModel class is created, its constructor accepts an ICatalogService type, which Autofac resolves, returning an instance of the CatalogService class. Дополнительные сведения о внедрения зависимостей, см. в разделе введение внедрения зависимостей.For more information about dependency injection, see Introduction to Dependency Injection.

Рис. 10-1 показано взаимодействие классов, которые считывают данные каталога из микрослужбы каталога для отображения CatalogView.Figure 10-1 shows the interaction of classes that read catalog data from the catalog microservice for displaying by the CatalogView.

Рис. 10-1: Получение данных из микрослужбы каталогаFigure 10-1: Retrieving data from the catalog microservice

Когда CatalogView осуществляется переход, OnInitialize метод в CatalogViewModel класс называется.When the CatalogView is navigated to, the OnInitialize method in the CatalogViewModel class is called. Этот метод возвращает данные каталога из микрослужбы каталога, как показано в следующем примере кода:This method retrieves catalog data from the catalog microservice, as demonstrated in the following code example:

public override async Task InitializeAsync(object navigationData)  
{  
    ...  
    Products = await _productsService.GetCatalogAsync();  
    ...  
}

Этот метод вызывает метод GetCatalogAsync метод CatalogService экземпляра, внедренном в CatalogViewModel по Autofac.This method calls the GetCatalogAsync method of the CatalogService instance that was injected into the CatalogViewModel by Autofac. Метод GetCatalogAsync показан в следующем примере кода:The following code example shows the GetCatalogAsync method:

public async Task<ObservableCollection<CatalogItem>> GetCatalogAsync()  
{  
    UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);  
    builder.Path = "api/v1/catalog/items";  
    string uri = builder.ToString();  

    CatalogRoot catalog = await _requestProvider.GetAsync<CatalogRoot>(uri);  
    ...  
    return catalog?.Data.ToObservableCollection();            
}

Этот метод создает URI, который определяет ресурс, запрос будет отправлен и использует RequestProvider класса для вызова метода GET HTTP для ресурса, перед возвратом результатов для CatalogViewModel.This method builds the URI that identifies the resource the request will be sent to, and uses the RequestProvider class to invoke the GET HTTP method on the resource, before returning the results to the CatalogViewModel. RequestProvider Класс содержит функциональные возможности, отправляет запрос в виде URI, идентифицирующий ресурс, метод HTTP, указывающее операцию для выполнения на этот ресурс, и текст, который содержит все данные, необходимые для выполнения операции.The RequestProvider class contains functionality that submits a request in the form of a URI that identifies a resource, an HTTP method that indicates the operation to be performed on that resource, and a body that contains any data required to perform the operation. Сведения о том, как RequestProvider класс внедряется в CatalogService class, см. в разделе введение внедрения зависимостей.For information about how the RequestProvider class is injected into the CatalogService class, see Introduction to Dependency Injection.

В следующем коде показано в примере GetAsync метод в RequestProvider класса:The following code example shows the GetAsync method in the RequestProvider class:

public async Task<TResult> GetAsync<TResult>(string uri, string token = "")  
{  
    HttpClient httpClient = CreateHttpClient(token);  
    HttpResponseMessage response = await httpClient.GetAsync(uri);  

    await HandleResponse(response);  
    string serialized = await response.Content.ReadAsStringAsync();  

    TResult result = await Task.Run(() =>   
        JsonConvert.DeserializeObject<TResult>(serialized, _serializerSettings));  

    return result;  
}

Этот метод вызывает метод CreateHttpClient метод, который возвращает экземпляр HttpClient класс с набором соответствующие заголовки.This method calls the CreateHttpClient method, which returns an instance of the HttpClient class with the appropriate headers set. Затем он отправляет асинхронный запрос GET для ресурса с URI, с ответом, хранящихся в HttpResponseMessage экземпляра.It then submits an asynchronous GET request to the resource identified by the URI, with the response being stored in the HttpResponseMessage instance. HandleResponse Затем вызывается метод, который создает исключение, если ответ не включает код состояния HTTP успешно.The HandleResponse method is then invoked, which throws an exception if the response doesn't include a success HTTP status code. Затем ответ читается как строку, преобразованную из формата JSON для CatalogRoot объекта, а возвращается в CatalogService.Then the response is read as a string, converted from JSON to a CatalogRoot object, and returned to the CatalogService.

CreateHttpClient Метод показан в следующем примере кода:The CreateHttpClient method is shown in the following code example:

private HttpClient CreateHttpClient(string token = "")  
{  
    var httpClient = new HttpClient();  
    httpClient.DefaultRequestHeaders.Accept.Add(  
        new MediaTypeWithQualityHeaderValue("application/json"));  

    if (!string.IsNullOrEmpty(token))  
    {  
        httpClient.DefaultRequestHeaders.Authorization =   
            new AuthenticationHeaderValue("Bearer", token);  
    }  
    return httpClient;  
}

Этот метод создает новый экземпляр класса HttpClient и задает Accept заголовок любых запросов, сделанных HttpClient экземпляр application/json, указывает, что метод ожидает содержимое сообщения ответа, которые необходимо отформатировать с помощью JSON.This method creates a new instance of the HttpClient class, and sets the Accept header of any requests made by the HttpClient instance to application/json, which indicates that it expects the content of any response to be formatted using JSON. Затем, если маркер доступа был передан в качестве аргумента для CreateHttpClient , он добавляется метод Authorization заголовок любых запросов, сделанных HttpClient экземпляра, префикс строки Bearer.Then, if an access token was passed as an argument to the CreateHttpClient method, it's added to the Authorization header of any requests made by the HttpClient instance, prefixed with the string Bearer. Дополнительные сведения об авторизации см. в разделе авторизации.For more information about authorization, see Authorization.

Когда GetAsync метод в RequestProvider вызываемый классом HttpClient.GetAsync, Items метод в CatalogController вызывается класс в проекте Catalog.API, как показано в следующем примере кода:When the GetAsync method in the RequestProvider class calls HttpClient.GetAsync, the Items method in the CatalogController class in the Catalog.API project is invoked, which is shown in the following code example:

[HttpGet]  
[Route("[action]")]  
public async Task<IActionResult> Items(  
    [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)  
{  
    var totalItems = await _catalogContext.CatalogItems  
        .LongCountAsync();  

    var itemsOnPage = await _catalogContext.CatalogItems  
        .OrderBy(c=>c.Name)  
        .Skip(pageSize * pageIndex)  
        .Take(pageSize)  
        .ToListAsync();  

    itemsOnPage = ComposePicUri(itemsOnPage);  
    var model = new PaginatedItemsViewModel<CatalogItem>(  
        pageIndex, pageSize, totalItems, itemsOnPage);             

    return Ok(model);  
}

Этот метод извлекает данные каталога из базы данных SQL с использованием EntityFramework и возвращает его как ответное сообщение, включающий успешно код состояния HTTP и коллекция JSON в формате CatalogItem экземпляров.This method retrieves the catalog data from the SQL database using EntityFramework, and returns it as a response message that includes a success HTTP status code, and a collection of JSON formatted CatalogItem instances.

Формирование запроса POSTMaking a POST Request

BasketService Класс используется для управления извлечения данных и обновления процесс с микрослужбой basket.The BasketService class is used to manage the data retrieval and update process with the basket microservice. В RegisterDependencies метод в ViewModelLocator класс, BasketService класс регистрируется как сопоставление типов для IBasketService типа с помощью контейнера внедрения зависимостей Autofac.In the RegisterDependencies method in the ViewModelLocator class, the BasketService class is registered as a type mapping against the IBasketService type with the Autofac dependency injection container. Теперь, когда экземпляр BasketViewModel создается класс, его конструктор принимает IBasketService тип, который разрешает Autofac, возвращение экземпляра BasketService класса.Then, when an instance of the BasketViewModel class is created, its constructor accepts an IBasketService type, which Autofac resolves, returning an instance of the BasketService class. Дополнительные сведения о внедрения зависимостей, см. в разделе введение внедрения зависимостей.For more information about dependency injection, see Introduction to Dependency Injection.

Рис. 10-2 показано взаимодействие классов, которые отправляют данных корзины, отображаемых объектом BasketView, чтобы микрослужба корзины.Figure 10-2 shows the interaction of classes that send the basket data displayed by the BasketView, to the basket microservice.

Рис. 10-2: Отправляет данные в микрослужбе корзиныFigure 10-2: Sending data to the basket microservice

При добавлении элемента в корзину ReCalculateTotalAsync метод в BasketViewModel класс называется.When an item is added to the shopping basket, the ReCalculateTotalAsync method in the BasketViewModel class is called. Этот метод обновляет общее число элементов в корзине и отправляет данные корзины в микрослужбе корзины, как показано в следующем примере кода:This method updates the total value of items in the basket, and sends the basket data to the basket microservice, as demonstrated in the following code example:

private async Task ReCalculateTotalAsync()  
{  
    ...  
    await _basketService.UpdateBasketAsync(new CustomerBasket  
    {  
        BuyerId = userInfo.UserId,   
        Items = BasketItems.ToList()  
    }, authToken);  
}

Этот метод вызывает метод UpdateBasketAsync метод BasketService экземпляра, внедренном в BasketViewModel по Autofac.This method calls the UpdateBasketAsync method of the BasketService instance that was injected into the BasketViewModel by Autofac. В следующем показан метод UpdateBasketAsync метод:The following method shows the UpdateBasketAsync method:

public async Task<CustomerBasket> UpdateBasketAsync(CustomerBasket customerBasket, string token)  
{  
    UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint);  
    string uri = builder.ToString();  
    var result = await _requestProvider.PostAsync(uri, customerBasket, token);  
    return result;  
}

Этот метод создает URI, который определяет ресурс, запрос будет отправлен и использует RequestProvider класса для вызова метода POST HTTP для ресурса, перед возвратом результатов для BasketViewModel.This method builds the URI that identifies the resource the request will be sent to, and uses the RequestProvider class to invoke the POST HTTP method on the resource, before returning the results to the BasketViewModel. Обратите внимание, что маркер доступа, полученный из IdentityServer во время процесса проверки подлинности, требуется для авторизации запросов в микрослужбе корзины.Note that an access token, obtained from IdentityServer during the authentication process, is required to authorize requests to the basket microservice. Дополнительные сведения об авторизации см. в разделе авторизации.For more information about authorization, see Authorization.

В следующем примере кода показан один из PostAsync методы в RequestProvider класса:The following code example shows one of the PostAsync methods in the RequestProvider class:

public async Task<TResult> PostAsync<TResult>(  
    string uri, TResult data, string token = "", string header = "")  
{  
    HttpClient httpClient = CreateHttpClient(token);  
    ...  
    var content = new StringContent(JsonConvert.SerializeObject(data));  
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");  
    HttpResponseMessage response = await httpClient.PostAsync(uri, content);  

    await HandleResponse(response);  
    string serialized = await response.Content.ReadAsStringAsync();  

    TResult result = await Task.Run(() =>  
        JsonConvert.DeserializeObject<TResult>(serialized, _serializerSettings));  

    return result;  
}

Этот метод вызывает метод CreateHttpClient метод, который возвращает экземпляр HttpClient класс с набором соответствующие заголовки.This method calls the CreateHttpClient method, which returns an instance of the HttpClient class with the appropriate headers set. Затем он отправляет асинхронный запрос POST для ресурса с URI, с данными сериализованный корзины, отправляемых в формате JSON и ответа, сохраняемого в HttpResponseMessage экземпляра.It then submits an asynchronous POST request to the resource identified by the URI, with the serialized basket data being sent in JSON format, and the response being stored in the HttpResponseMessage instance. HandleResponse Затем вызывается метод, который создает исключение, если ответ не включает код состояния HTTP успешно.The HandleResponse method is then invoked, which throws an exception if the response doesn't include a success HTTP status code. Затем ответ читается как строку, преобразованную из формата JSON для CustomerBasket объекта, а возвращается в BasketService.Then, the response is read as a string, converted from JSON to a CustomerBasket object, and returned to the BasketService. Дополнительные сведения о CreateHttpClient метод, см. в разделе внесения получить запрос на.For more information about the CreateHttpClient method, see Making a GET Request.

Когда PostAsync метод в RequestProvider вызываемый классом HttpClient.PostAsync, Post метод в BasketController вызывается класс в проекте Basket.API, как показано в следующем примере кода:When the PostAsync method in the RequestProvider class calls HttpClient.PostAsync, the Post method in the BasketController class in the Basket.API project is invoked, which is shown in the following code example:

[HttpPost]  
public async Task<IActionResult> Post([FromBody]CustomerBasket value)  
{  
    var basket = await _repository.UpdateBasketAsync(value);  
    return Ok(basket);  
}

Этот метод использует экземпляр RedisBasketRepository класса для сохранения данных корзины в кэш Redis и возвращает его, отформатированное сообщение ответа, которое включает в себя успешно код состояния HTTP и JSON CustomerBasket экземпляра.This method uses an instance of the RedisBasketRepository class to persist the basket data to the Redis cache, and returns it as a response message that includes a success HTTP status code, and a JSON formatted CustomerBasket instance.

Выполнении запроса на удалениеMaking a DELETE Request

Рис. 10-3 показано взаимодействие классов, которые удаления устаревших данных корзины в микрослужбе корзины, CheckoutView.Figure 10-3 shows the interactions of classes that delete basket data from the basket microservice, for the CheckoutView.

Рис. 10-3: Удаление данных из микрослужба корзиныFigure 10-3: Deleting data from the basket microservice

При вызове процесс подсчета стоимости покупок CheckoutAsync метод в CheckoutViewModel класс называется.When the checkout process is invoked, the CheckoutAsync method in the CheckoutViewModel class is called. Этот метод создает новый заказ, перед удалением корзины покупок, как показано в следующем примере кода:This method creates a new order, before clearing the shopping basket, as demonstrated in the following code example:

private async Task CheckoutAsync()  
{  
    ...  
    await _basketService.ClearBasketAsync(_shippingAddress.Id.ToString(), authToken);  
    ...  
}

Этот метод вызывает метод ClearBasketAsync метод BasketService экземпляра, внедренном в CheckoutViewModel по Autofac.This method calls the ClearBasketAsync method of the BasketService instance that was injected into the CheckoutViewModel by Autofac. В следующем показан метод ClearBasketAsync метод:The following method shows the ClearBasketAsync method:

public async Task ClearBasketAsync(string guidUser, string token)  
{  
    UriBuilder builder = new UriBuilder(GlobalSetting.Instance.BasketEndpoint);  
    builder.Path = guidUser;  
    string uri = builder.ToString();  
    await _requestProvider.DeleteAsync(uri, token);  
}

Этот метод создает URI, идентифицирующий ресурс, который будет отправляться запрос и использует RequestProvider класса для вызова метода DELETE HTTP в ресурсе.This method builds the URI that identifies the resource that the request will be sent to, and uses the RequestProvider class to invoke the DELETE HTTP method on the resource. Обратите внимание, что маркер доступа, полученный из IdentityServer во время процесса проверки подлинности, требуется для авторизации запросов в микрослужбе корзины.Note that an access token, obtained from IdentityServer during the authentication process, is required to authorize requests to the basket microservice. Дополнительные сведения об авторизации см. в разделе авторизации.For more information about authorization, see Authorization.

В следующем коде показано в примере DeleteAsync метод в RequestProvider класса:The following code example shows the DeleteAsync method in the RequestProvider class:

public async Task DeleteAsync(string uri, string token = "")  
{  
    HttpClient httpClient = CreateHttpClient(token);  
    await httpClient.DeleteAsync(uri);  
}

Этот метод вызывает метод CreateHttpClient метод, который возвращает экземпляр HttpClient класс с набором соответствующие заголовки.This method calls the CreateHttpClient method, which returns an instance of the HttpClient class with the appropriate headers set. Затем он отправляет асинхронный запрос DELETE к ресурсу, указанному в URI.It then submits an asynchronous DELETE request to the resource identified by the URI. Дополнительные сведения о CreateHttpClient метод, см. в разделе внесения получить запрос на.For more information about the CreateHttpClient method, see Making a GET Request.

Когда DeleteAsync метод в RequestProvider вызываемый классом HttpClient.DeleteAsync, Delete метод в BasketController вызывается класс в проекте Basket.API, как показано в следующем примере кода:When the DeleteAsync method in the RequestProvider class calls HttpClient.DeleteAsync, the Delete method in the BasketController class in the Basket.API project is invoked, which is shown in the following code example:

[HttpDelete("{id}")]  
public void Delete(string id)  
{  
    _repository.DeleteBasketAsync(id);  
}

Этот метод использует экземпляр RedisBasketRepository класса, чтобы удалить данные корзины из кэша Redis.This method uses an instance of the RedisBasketRepository class to delete the basket data from the Redis cache.

Кэширование данныхCaching Data

Можно повысить производительность приложения путем кэширования часто используемых данных в быстрое хранилище, расположенное ближе к приложению.The performance of an app can be improved by caching frequently accessed data to fast storage that's located close to the app. Если устройство хранения расположен ближе к приложению, чем исходный оригинал, то кэширование может значительно повысить ответа время ожидания при получении данных.If the fast storage is located closer to the app than the original source, then caching can significantly improve response times when retrieving data.

Наиболее распространенная форма кэширования является сквозного чтения кэширования, где приложение извлекает данные, ссылаясь на кэш.The most common form of caching is read-through caching, where an app retrieves data by referencing the cache. Если данные находятся не в кэше, извлекаются из хранилища данных и добавляются в кэш.If the data isn't in the cache, it's retrieved from the data store and added to the cache. Приложения можно реализовать сквозного чтения кэширования с шаблоном "кэш".Apps can implement read-through caching with the cache-aside pattern. Этот шаблон определяет, находится ли элемент в кэше.This pattern determines whether the item is currently in the cache. Если элемент отсутствует в кэше, чтение из хранилища данных и добавляются в кэш.If the item isn't in the cache, it's read from the data store and added to the cache. Дополнительные сведения см. в разделе кэш на стороне шаблон.For more information, see the Cache-Aside pattern.

Совет

Кэширование данных часто читаемых и изменяются редко.Cache data that's read frequently and that changes infrequently. Эти данные могут добавляться в кэш по запросу первый раз, он извлекается приложением.This data can be added to the cache on demand the first time it is retrieved by an app. Это означает, что приложению необходимо получить только один раз данные из хранилища данных и последующие доступа могут выполняться с помощью кэша.This means that the app needs to fetch the data only once from the data store, and that subsequent access can be satisfied by using the cache.

Распределенные приложения, такие как эталонное приложение eShopOnContainers, должен предоставить одно или оба указанных ниже кэши:Distributed applications, such as the eShopOnContainers reference application, should provide either or both of the following caches:

  • Общий кэш, которую можно запустить несколько процессов или машин.A shared cache, which can be accessed by multiple processes or machines.
  • Частный кэш, где данные хранятся локально на устройстве, запустив его.A private cache, where data is held locally on the device running the app.

Мобильное приложение eShopOnContainers использует частный кэш, где данные хранятся локально на устройстве, на котором выполняется экземпляр приложения.The eShopOnContainers mobile app uses a private cache, where data is held locally on the device that's running an instance of the app. Сведения о кэше, используемые в образце приложения eShopOnContainers, см. в разделе Микрослужбы .NET: архитектура контейнерных приложений .NET.For information about the cache used by the eShopOnContainers reference application, see .NET Microservices: Architecture for Containerized .NET Applications.

Совет

Можно Рассматривайте кэш как хранилище временных данных, которое может стать недоступным в любое время.Think of the cache as a transient data store that could disappear at any time. Убедитесь, что данные хранятся в хранилище исходных данных, а также в кэше.Ensure that data is maintained in the original data store as well as the cache. Затем к минимуму вероятность потери данных, если кэш становится недоступным.The chances of losing data are then minimized if the cache becomes unavailable.

Управление истечением срока актуальности данныхManaging Data Expiration

Нецелесообразно ожидать, что кэшированные данные всегда будут согласованы с исходными данными.It's impractical to expect that cached data will always be consistent with the original data. Данные в хранилище исходных данных может измениться после он был кэширован, вызывая кэшированные данные устаревают.Data in the original data store might change after it's been cached, causing the cached data to become stale. Таким образом приложения должны реализовать стратегию, которая позволяет гарантировать, что данные в кэше, как максимально актуальны, но можно также обнаруживать и обработать ситуации, возникающие, когда данные в кэше устарели.Therefore, apps should implement a strategy that helps to ensure that the data in the cache is as up-to-date as possible, but can also detect and handle situations that arise when the data in the cache has become stale. Наиболее кэширования Включить кэш быть перенастроены на истечение срока хранения данных и таким образом уменьшить период, для которого данные могут быть устаревшими.Most caching mechanisms enable the cache to be configured to expire data, and hence reduce the period for which data might be out of date.

Совет

Значение по умолчанию время при настройке кэша.Set a default expiration time when configuring a cache. Многие кэши реализуют истечения срока действия, которая объявляет данные недействительными и удаляет его из кэша, если они недоступны в течение указанного периода.Many caches implement expiration, which invalidates data and removes it from the cache if it's not accessed for a specified period. Тем не менее необходимо соблюдать осторожность при выборе срока действия.However, care must be taken when choosing the expiration period. Если он становится слишком короткий, данных устареют слишком быстро, и преимущества кэширования, которые будет снижена.If it's made too short, data will expire too quickly and the benefits of caching will be reduced. Если он становится слишком много времени, данные риски, перестанут быть актуальными.If it's made too long, the data risks becoming stale. Таким образом время окончания срока действия должно соответствовать шаблону доступа для приложений, использующих данные.Therefore, the expiration time should match the pattern of access for apps that use the data.

Когда кэшированные данные устаревают, должны удаляться из кэша и приложение должно получить данные из исходных данных хранения и поместите его обратно в кэш.When cached data expires, it should be removed from the cache, and the app must retrieve the data from the original data store and place it back into the cache.

Это также возможно, что переполнение кэша, если данные могут оставаться слишком долго.It's also possible that a cache might fill up if data is allowed to remain for too long a period. Таким образом, запросы на добавление новых элементов в кэш может потребоваться удалить некоторые элементы в рамках процесса под названием вытеснения.Therefore, requests to add new items to the cache might be required to remove some items in a process known as eviction. Службы кэширования обычно исключают данные на основе наименее недавно использовавшихся.Caching services typically evict data on a least-recently-used basis. Тем не менее существуют другие политики вытеснения, в том числе, недавно использованные и первый in-first-out. Дополнительные сведения см. в разделе руководстве по кэшированию.However, there are other eviction policies, including most-recently-used, and first-in-first-out. For more information, see Caching Guidance.

Кэширование изображенийCaching Images

Мобильное приложение eShopOnContainers использует изображения удаленных продуктов, которые получают преимущества от кэширования.The eShopOnContainers mobile app consumes remote product images that benefit from being cached. Эти изображения отображаются по Image элемента управления и CachedImage управление, предоставляемое FFImageLoading библиотеки.These images are displayed by the Image control, and the CachedImage control provided by the FFImageLoading library.

Xamarin.Forms Image элемент управления поддерживает кэширование загруженных изображений.The Xamarin.Forms Image control supports caching of downloaded images. Кэширование включено по умолчанию и сохраняется локально на 24 часа.Caching is enabled by default, and will store the image locally for 24 hours. Кроме того, можно настроить срок действия CacheValidity свойство.In addition, the expiration time can be configured with the CacheValidity property. Дополнительные сведения см. в разделе Скачанный образ кэширование.For more information, see Downloaded Image Caching.

В FFImageLoading CachedImage управления — это замена для Xamarin.Forms Image элемента управления, предоставляя дополнительные свойства, включения дополнительных функций.FFImageLoading's CachedImage control is a replacement for the Xamarin.Forms Image control, providing additional properties that enable supplementary functionality. Для этой функции элемент управления обеспечивает можно настроить кэширование, при поддержке ошибки и загрузки изображения-заполнители.Amongst this functionality, the control provides configurable caching, while supporting error and loading image placeholders. В следующем примере кода показано, как мобильное приложение eShopOnContainers использует CachedImage контролировать, ProductTemplate, который является шаблон данных, используемые ListView контролировать CatalogView:The following code example shows how the eShopOnContainers mobile app uses the CachedImage control in the ProductTemplate, which is the data template used by the ListView control in the CatalogView:

<ffimageloading:CachedImage
    Grid.Row="0"
    Source="{Binding PictureUri}"     
    Aspect="AspectFill">
    <ffimageloading:CachedImage.LoadingPlaceholder>
        <OnPlatform x:TypeArguments="ImageSource">
            <On Platform="iOS, Android" Value="default_campaign" />
            <On Platform="UWP" Value="Assets/default_campaign.png" />
        </OnPlatform>
    </ffimageloading:CachedImage.LoadingPlaceholder>
    <ffimageloading:CachedImage.ErrorPlaceholder>
        <OnPlatform x:TypeArguments="ImageSource">
            <On Platform="iOS, Android" Value="noimage" />
            <On Platform="UWP" Value="Assets/noimage.png" />
        </OnPlatform>
    </ffimageloading:CachedImage.ErrorPlaceholder>
</ffimageloading:CachedImage>

CachedImage Задает LoadingPlaceholder и ErrorPlaceholder свойства для образов платформы.The CachedImage control sets the LoadingPlaceholder and ErrorPlaceholder properties to platform-specific images. LoadingPlaceholder Свойство задает изображение, отображаемое при изображение, указанное Source свойство получено и ErrorPlaceholder свойство задает изображение, отображаемое, если произошла ошибка при попытке получения изображения определяется Source свойство.The LoadingPlaceholder property specifies the image to be displayed while the image specified by the Source property is retrieved, and the ErrorPlaceholder property specifies the image to be displayed if an error occurs when attempting to retrieve the image specified by the Source property.

Как и предполагает название, CachedImage управления кэширует удаленного изображения на устройстве для времени, заданного параметром значения CacheDuration свойство.As the name implies, the CachedImage control caches remote images on the device for the time specified by the value of the CacheDuration property. Если значение этого свойства не задано явно, применяется значение по умолчанию 30 дней.When this property value isn't explicitly set, the default value of 30 days is applied.

Повышение устойчивостиIncreasing Resilience

Все приложения, которые обмениваются данными с удаленными службами и ресурсами должен быть чувствительны ко временным сбоям.All apps that communicate with remote services and resources must be sensitive to transient faults. Временные сбои включают кратковременной потерей сетевого подключения для служб, временную недоступность службы или наличие времени ожидания, когда служба занята.Transient faults include the momentary loss of network connectivity to services, the temporary unavailability of a service, or timeouts that arise when a service is busy. Эти ошибки часто устраняются, и если повторить действие через некоторый промежуток вполне вероятно, для успешного выполнения.These faults are often self-correcting, and if the action is repeated after a suitable delay it's likely to succeed.

Временные сбои может иметь огромное влияние на качество предполагаемых приложения, даже если оно тщательно протестировано во всех ожидаемых обстоятельствах.Transient faults can have a huge impact on the perceived quality of an app, even if it has been thoroughly tested under all foreseeable circumstances. Чтобы надежно работает приложение, которое обменивается данными с удаленными службами, необходимо иметь возможность выполнять все указанные ниже:To ensure that an app that communicates with remote services operates reliably, it must be able to do all of the following:

  • Обнаруживать ошибки, при их возникновения и определить, если сообщения об ошибках, скорее всего, будут временными.Detect faults when they occur, and determine if the faults are likely to be transient.
  • Повторите операцию, если определит, что сбой является скорее всего, будут временными и отслеживать количество повторных попыток операция.Retry the operation if it determines that the fault is likely to be transient and keep track of the number of times the operation was retried.
  • Использование стратегии повтора, который указывает количество повторных попыток, задержку между попытками и действия для использования после неудачной попытки.Use an appropriate retry strategy, which specifies the number of retries, the delay between each attempt, and the actions to take after a failed attempt.

Эта обработка временного сбоя достигается путем заключения всех попыток доступа к удаленной службе в коде, реализующем шаблон повторных попыток.This transient fault handling can be achieved by wrapping all attempts to access a remote service in code that implements the retry pattern.

Шаблон повторовRetry Pattern

Если приложение обнаруживает сбой при попытке отправить запрос к удаленной службе, он может обработать этот сбой в любой из следующих способов:If an app detects a failure when it tries to send a request to a remote service, it can handle the failure in any of the following ways:

  • Повторное выполнение данной операции.Retrying the operation. Приложение может повторить запрос сбоя сразу же.The app could retry the failing request immediately.
  • Повторите операцию через некоторое время.Retrying the operation after a delay. Приложение следует подождать подходящее количество времени до повторным выполнением запроса.The app should wait for a suitable amount of time before retrying the request.
  • Отмена операции.Cancelling the operation. Приложение должно отменить операцию и сформировать отчет об исключении.The application should cancel the operation and report an exception.

Используемая стратегия повторных попыток должен быть настроен так, в соответствии с бизнес-требований приложения.The retry strategy should be tuned to match the business requirements of the app. Например очень важно оптимизировать число повторных попыток и интервал для предпринятой операции повтора.For example, it's important to optimize the retry count and retry interval to the operation being attempted. Если операция является частью взаимодействия с пользователем, интервал повторных попыток должно быть Краткосрочный и всего несколько повторных попыток, чтобы не заставлять пользователя дожидаться ответа.If the operation is part of a user interaction, the retry interval should be short and only a few retries attempted to avoid making users wait for a response. Если операция является частью долго выполняющегося рабочего процесса, когда Отмена и перезапуск рабочего процесса является дорогостоящим или много времени, он подходит для ожидания между повторными и повторить несколько раз.If the operation is part of a long running workflow, where cancelling or restarting the workflow is expensive or time-consuming, it's appropriate to wait longer between attempts and to retry more times.

Примечание

Стратегии Агрессивный Повтор с минимальной задержкой между попытками и большое количество повторных попыток, может привести к снижению удаленной службы, на котором выполняется ближе к или достигнуто максимальное число.An aggressive retry strategy with minimal delay between attempts, and a large number of retries, could degrade a remote service that's running close to or at capacity. Кроме того такая стратегия повторных попыток также может повлиять на скорость реагирования приложения, если оно непрерывно пытается выполнить операцию, завершившуюся сбоем.In addition, such a retry strategy could also affect the responsiveness of the app if it's continually trying to perform a failing operation.

Если запрос по-прежнему не работает после количества повторных попыток, лучше для приложения, чтобы предотвратить дальнейшие запросы к тому же ресурсу и сообщение об ошибке.If a request still fails after a number of retries, it's better for the app to prevent further requests going to the same resource and to report a failure. Затем после определенного периода, приложение может сделать один или несколько запросов к ресурсу, чтобы узнать, если они успешно.Then, after a set period, the app can make one or more requests to the resource to see if they're successful. Дополнительные сведения см. в разделе шаблон автоматического выключения.For more information, see Circuit Breaker Pattern.

Совет

Никогда не применяйте механизм с бесконечными повторными попытками.Never implement an endless retry mechanism. Используйте конечное число повторных попыток или реализуйте Размыкатель цепи шаблон, чтобы разрешить службе для восстановления.Use a finite number of retries, or implement the Circuit Breaker pattern to allow a service to recover.

В мобильном приложении eShopOnContainers пока не реализованы шаблона повторных попыток при создании запросов к веб-RESTful.The eShopOnContainers mobile app does not currently implement the retry pattern when making RESTful web requests. Тем не менее CachedImage элемента управления, предоставляемые FFImageLoading библиотека поддерживает обработки временных сбоев, повторив попытку загрузки образа.However, the CachedImage control, provided by the FFImageLoading library supports transient fault handling by retrying image loading. В случае сбоя загрузки изображений дальнейшие попытки больше выполняться.If image loading fails, further attempts will be made. Число попыток задается RetryCount свойство и повторных попыток произойдет после задержки, заданной RetryDelay свойство.The number of attempts is specified by the RetryCount property, and retries will occur after a delay specified by the RetryDelay property. Если значения этих свойств не задано явно, по умолчанию применяются значения — 3 для RetryCount свойство и 250 мс для RetryDelay свойство.If these property values aren't explicitly set, their default values are applied – 3 for the RetryCount property, and 250ms for the RetryDelay property. Дополнительные сведения о CachedImage управления, см. в разделе кэширования изображений.For more information about the CachedImage control, see Caching Images.

Образце приложения eShopOnContainers реализации шаблона повторных попыток.The eShopOnContainers reference application does implement the retry pattern. Дополнительные сведения, в том числе о том, как объединить шаблона повторных попыток с HttpClient , представлена в разделе Микрослужбы .NET: архитектура контейнерных приложений .NET.For more information, including a discussion of how to combine the retry pattern with the HttpClient class, see .NET Microservices: Architecture for Containerized .NET Applications.

Дополнительные сведения о шаблоне повторных попыток, см. в разделе повторите шаблон.For more information about the retry pattern, see the Retry pattern.

Шаблон автоматического выключенияCircuit Breaker Pattern

В некоторых ситуациях ошибки может произойти из-за ожидаемой событий, которые принимают больше времени, чтобы исправить.In some situations, faults can occur due to anticipated events that take longer to fix. Такие сбои могут быть от частичной потери подключения до полного отказа службы.These faults can range from a partial loss of connectivity to the complete failure of a service. В таких ситуациях не имеет смысла, если для приложения повторить операцию, которая, скорее всего, выполняются успешно и вместо этого следует принимать, что операция завершилась ошибкой и обработать его.In these situations, it's pointless for an app to retry an operation that's unlikely to succeed, and instead should accept that the operation has failed and handle this failure accordingly.

Шаблон автоматического выключения может препятствовать приложение несколько раз пытается выполнить операцию, которая, вероятнее всего переход на другой, а также приложение, чтобы определить, устранена ли ошибка.The circuit breaker pattern can prevent an app from repeatedly trying to execute an operation that's likely to fail, while also enabling the app to detect whether the fault has been resolved.

Примечание

Назначение шаблона размыкателя цепи отличается от шаблона повторных попыток.The purpose of the circuit breaker pattern is different from the retry pattern. Шаблон повторов позволяет приложению повторять операцию, ожидая, что она будет успешного выполнена.The retry pattern enables an app to retry an operation in the expectation that it'll succeed. Шаблон автоматического выключения препятствует выполнению операции, которая, скорее всего, сбой приложения.The circuit breaker pattern prevents an app from performing an operation that's likely to fail.

Автоматическое выключение действует как прокси для операций, которые может завершиться ошибкой.A circuit breaker acts as a proxy for operations that might fail. Прокси-сервер должен отслеживать количество недавних сбоев, произошедших и использовать эту информацию, чтобы решить, следует ли разрешить операцию продолжить, или же немедленно вернуть исключение.The proxy should monitor the number of recent failures that have occurred, and use this information to decide whether to allow the operation to proceed, or to return an exception immediately.

В мобильном приложении eShopOnContainers в настоящее время не реализует шаблон автоматического выключения.The eShopOnContainers mobile app does not currently implement the circuit breaker pattern. Тем не менее выполняет eShopOnContainers.However, the eShopOnContainers does. Дополнительные сведения см. в разделе Микрослужбы .NET: архитектура контейнерных приложений .NET.For more information, see .NET Microservices: Architecture for Containerized .NET Applications.

Совет

Объедините шаблоны повторных попыток и Размыкатель цепи.Combine the retry and circuit breaker patterns. Приложение можно объединять шаблоны повторных попыток и Размыкатель цепи с помощью шаблона повторных попыток попытка вызвать операцию через автоматический выключатель.An app can combine the retry and circuit breaker patterns by using the retry pattern to invoke an operation through a circuit breaker. Тем не менее логика повторных попыток должно быть чувствительно к любым исключениям, возвращаемым автоматическим выключением и отказываться от повторных попыток, если Размыкатель цепи сообщает, что неисправность не является временной.However, the retry logic should be sensitive to any exceptions returned by the circuit breaker and abandon retry attempts if the circuit breaker indicates that a fault is not transient.

Дополнительные сведения о шаблон автоматического выключения, см. в разделе Размыкатель цепи шаблон.For more information about the circuit breaker pattern, see the Circuit Breaker pattern.

СводкаSummary

Многие современные решения на основе веб-сделать использование веб-служб, размещенных на веб-серверах, для предоставления функций для удаленных клиентских приложений.Many modern web-based solutions make use of web services, hosted by web servers, to provide functionality for remote client applications. Операции, которые веб-служба предоставляет составляют веб-API, и клиентские приложения должны иметь возможность использовать веб-API, не зная, как реализованы данных или операций, которые предоставляет API-Интерфейс.The operations that a web service exposes constitute a web API, and client apps should be able to utilize the web API without knowing how the data or operations that the API exposes are implemented.

Можно повысить производительность приложения путем кэширования часто используемых данных в быстрое хранилище, расположенное ближе к приложению.The performance of an app can be improved by caching frequently accessed data to fast storage that's located close to the app. Приложения можно реализовать сквозного чтения кэширования с шаблоном "кэш".Apps can implement read-through caching with the cache-aside pattern. Этот шаблон определяет, находится ли элемент в кэше.This pattern determines whether the item is currently in the cache. Если элемент отсутствует в кэше, чтение из хранилища данных и добавляются в кэш.If the item isn't in the cache, it's read from the data store and added to the cache.

При взаимодействии с веб-API, приложения должны быть чувствительны ко временным сбоям.When communicating with web APIs, apps must be sensitive to transient faults. Временные сбои включают кратковременной потерей сетевого подключения для служб, временную недоступность службы или наличие времени ожидания, когда служба занята.Transient faults include the momentary loss of network connectivity to services, the temporary unavailability of a service, or timeouts that arise when a service is busy. Эти ошибки часто устраняются, и если повторить действие через некоторый промежуток, будет успешно выполнен.These faults are often self-correcting, and if the action is repeated after a suitable delay, then it's likely to succeed. Таким образом приложения следует заключить в нее все попытки доступа к веб-API в коде, который реализует механизм обработки временных сбоев.Therefore, apps should wrap all attempts to access a web API in code that implements a transient fault handling mechanism.