Не является стандартным термином в ASP.NET или ASP.NET Core. Возможно, имеется в виду подход к созданию запросов или API-методов в ASP.NET Core для обработки HTTP-запросов. Рассмотрим, как создавать и обрабатывать запросы в ASP.NET Core.
Контроллеры в ASP.NET Core отвечают за обработку HTTP-запросов и возврат ответов. Контроллеры обычно наследуются от класса
ControllerBase или Controller. using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[HttpGet("{id}")]
public IActionResult GetUser(int id)
{
var user = _userService.GetUserById(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}
[HttpPost]
public IActionResult CreateUser([FromBody] User user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_userService.CreateUser(user);
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
}
}
Сервисы содержат бизнес-логику приложения. Обычно они регистрируются в контейнере зависимостей.
public interface IUserService
{
User GetUserById(int id);
void CreateUser(User user);
}
public class UserService : IUserService
{
private readonly List<User> _users = new List<User>();
public User GetUserById(int id)
{
return _users.FirstOrDefault(u => u.Id == id);
}
public void CreateUser(User user)
{
user.Id = _users.Count + 1;
_users.Add(user);
}
}
Модель данных представляет структуру данных, с которой работает приложение.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Регистрация сервисов в
Startup.cs. public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<IUserService, UserService>();
}
Настройка маршрутизации для контроллеров в
Startup.cs. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
GET-запрос для получения пользователя
GET /api/users/1
POST-запрос для создания пользователя
POST /api/users
Content-Type: application/json
{
"name": "Alice",
"age": 30
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6👀1
Новые запросы к базе данных не могут быть обработаны, так как нет доступных подключений. Это приводит к тому, что запросы отклоняются или истекает время ожидания (timeout).
Запросы могут быть помещены в очередь и ждать доступного подключения, что увеличивает время отклика и снижает производительность системы.
Приложение может выбрасывать исключения, такие как
TimeoutException, SqlException (например, Cannot open connection), указывающие на невозможность установления соединения.try
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// Выполнение операций с базой данных
}
}
catch (SqlException ex)
{
Console.WriteLine("Ошибка подключения к базе данных: " + ex.Message);
}
catch (TimeoutException ex)
{
Console.WriteLine("Превышено время ожидания подключения: " + ex.Message);
}
Неосвобождение ресурсов: Пул подключений может исчерпаться, если подключения не закрываются и не возвращаются в пул после использования. Длительное удержание подключений: Подключения удерживаются слишком долго, например, при выполнении долгих операций в одной сессии.
Чрезмерное количество одновременно выполняемых запросов, превышающее максимальное количество доступных подключений в пуле.
Недостаточное количество максимальных подключений в пуле или слишком большое время ожидания подключения.
Всегда закрывайте соединения после использования, чтобы они возвращались в пул.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// Выполнение операций с базой данных
connection.Close(); // Явно закрываем подключение
}
Используйте конструкцию
using для автоматического закрытия соединений. using (var connection = new SqlConnection(connectionString))
{
connection.Open();
// Выполнение операций с базой данных
} // Подключение автоматически закрывается здесь
Увеличьте максимальное количество подключений в пуле.
var connectionString = "Data Source=server;Initial Catalog=database;User ID=user;Password=password;Max Pool Size=100;";
Настройте время ожидания подключения.
var connectionString = "Data Source=server;Initial Catalog=database;User ID=user;Password=password;Connection Timeout=30;";
Минимизируйте время удержания соединений. Используйте транзакции эффективно, чтобы не блокировать соединения на долгое время.
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
try
{
// Выполнение операций с базой данных
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥2
В ASP.NET Core можно выполнять действия до и после обработки запроса, не используя middleware, с помощью фильтров действий (Action Filters). Фильтры позволяют выполнять код до и после вызова метода контроллера.
Создадим фильтр, который выполняет код до и после метода действия контроллера.
using Microsoft.AspNetCore.Mvc.Filters;
using System;
public class MyActionFilter : Attribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// Код, выполняемый до действия контроллера
Console.WriteLine("До выполнения действия контроллера.");
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Код, выполняемый после действия контроллера
Console.WriteLine("После выполнения действия контроллера.");
}
}
Фильтр можно применить к конкретному методу контроллера или ко всему контроллеру.
using Microsoft.AspNetCore.Mvc;
public class MyController : Controller
{
[MyActionFilter]
public IActionResult MyAction()
{
// Логика действия контроллера
return Ok("Action executed");
}
}
Применение ко всему контроллеру
using Microsoft.AspNetCore.Mvc;
[MyActionFilter]
public class MyController : Controller
{
public IActionResult MyAction1()
{
// Логика действия контроллера
return Ok("Action 1 executed");
}
public IActionResult MyAction2()
{
// Логика действия контроллера
return Ok("Action 2 executed");
}
}
Фильтр также можно зарегистрировать глобально, чтобы он применялся ко всем контроллерам и действиям. Регистрация глобального фильтра в
Startup.cs using Microsoft.AspNetCore.Mvc;
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.Filters.Add<MyActionFilter>();
});
}
Создание фильтра
using Microsoft.AspNetCore.Mvc.Filters;
using System;
public class LoggingActionFilter : Attribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// Логика до выполнения действия контроллера
Console.WriteLine("Запрос начался: " + context.HttpContext.Request.Path);
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Логика после выполнения действия контроллера
Console.WriteLine("Запрос завершился: " + context.HttpContext.Request.Path);
}
}
Применение фильтра к контроллеру
using Microsoft.AspNetCore.Mvc;
[LoggingActionFilter]
public class UsersController : Controller
{
public IActionResult GetUser(int id)
{
// Логика действия контроллера
return Ok(new { Id = id, Name = "User" + id });
}
}
Регистрация в
Startup.cs public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Класс сервис-локатора хранит ссылки на сервисы и позволяет запрашивать их по идентификатору, что упрощает управление зависимостями.
Однако этот паттерн критикуют за скрытые зависимости и нарушение принципа инверсии зависимостей (SOLID).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1
Это популярный брокер сообщений, который используется для обмена сообщениями между различными компонентами системы. В RabbitMQ есть несколько базовых сущностей, которые нужно понимать для эффективного использования этой технологии.
Это данные, которые отправляются от отправителя к получателю через RabbitMQ. Сообщения могут содержать любые данные: текст, JSON, XML, двоичные данные и т.д.
Это места, где сообщения хранятся до тех пор, пока их не заберет получатель. Очереди обеспечивают надежную доставку сообщений и поддерживают множество получателей.
Создание очереди
rabbitmqadmin declare queue name=my_queue durable=true
Принимают сообщения от отправителей и направляют их в соответствующие очереди на основе правил маршрутизации. Существует несколько типов обменников:
Direct: Сообщения направляются в очередь с ключом маршрутизации, точно соответствующим ключу, указанному в обменнике.
Fanout: Сообщения направляются во все очереди, связанные с этим обменником, без учета ключа маршрутизации.
Topic: Сообщения направляются в очереди на основе шаблонов ключей маршрутизации.
Headers: Сообщения направляются в очереди на основе соответствия заголовков.
Создание обменника:
rabbitmqadmin declare exchange name=my_exchange type=direct durable=true
Определяют правила маршрутизации между обменниками и очередями. Они указывают, какие ключи маршрутизации должны использоваться для доставки сообщений из обменника в очередь.
Создание связи
rabbitmqadmin declare binding source=my_exchange destination=my_queue routing_key=my_key
Ключи маршрутизации используются обменниками для определения, в какие очереди направлять сообщения. Они играют ключевую роль при использовании
direct и topic обменников.Это приложения или службы, которые получают сообщения из очередей и обрабатывают их. Пример производителя на Python
import pika
def callback(ch, method, properties, body):
print(f"Received {body}")
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='my_queue')
channel.basic_consume(queue='my_queue', on_message_callback=callback, auto_ack=True)
print('Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
Это приложения или службы, которые отправляют сообщения в обменники RabbitMQ. Пример производителя на Python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='my_queue')
channel.basic_publish(exchange='', routing_key='my_queue', body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
В языке Python, например, метод get применяется к словарям для безопасного извлечения значения по ключу, возвращая None или значение по умолчанию, если ключ отсутствует.
В JavaScript get может быть геттером, определяющим, как получить значение свойства объекта при его доступе.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4👾1
Типы данных можно классифицировать по нескольким критериям, включая базовые категории, такие как значимые типы (value types) и ссылочные типы (reference types), а также другие характеристики, такие как встроенные типы, пользовательские типы и системы типов.
Значимые типы хранят свои значения непосредственно и обычно располагаются в стеке. При присваивании переменной значимого типа другой переменной создается копия значения.
int a = 10;
int b = a; // b получит копию значения a
Пользовательские типы, которые объединяют несколько значений.
struct Point
{
public int X;
public int Y;
}
Point p1 = new Point { X = 1, Y = 2 };
Point p2 = p1; // p2 получит копию значений p1
Типы, представляющие набор именованных констант.
enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
Days today = Days.Monday;Ссылочные типы хранят ссылки на объекты, которые располагаются в куче (heap). При присваивании переменной ссылочного типа другой переменной копируется ссылка на объект, а не сам объект.
Основные строительные блоки объектов.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person p1 = new Person { Name = "Alice", Age = 30 };
Person p2 = p1; // p2 указывает на тот же объект, что и p1
Контракты, определяющие набор методов и свойств, которые должны быть реализованы классами.
interface IAnimal
{
void Speak();
}
class Dog : IAnimal
{
public void Speak() => Console.WriteLine("Woof!");
}
Типы, представляющие ссылки на методы.
delegate void MyDelegate(string message);
MyDelegate del = Console.WriteLine;
del("Hello, World!");
Коллекции элементов одного типа.
int[] numbers = new int[] { 1, 2, 3, 4, 5 }; Последовательности символов.
string greeting = "Hello, World!";
Nullable типы позволяют значимым типам принимать значение
null, что означает отсутствие значения.int? nullableInt = null;
Обобщенные типы позволяют создавать классы, методы и структуры, которые могут работать с любыми типами данных, обеспечивая типобезопасность и повторное использование кода.
class GenericClass<T>
{
public T Value { get; set; }
}
GenericClass<int> intInstance = new GenericClass<int> { Value = 10 };
GenericClass<string> stringInstance = new GenericClass<string> { Value = "Hello" };
Неуправляемые типы позволяют работать с указателями и выполнять низкоуровневые операции, которые обычно не разрешены в безопасном управляемом коде.
unsafe
{
int x = 10;
int* ptr = &x;
Console.WriteLine((int)ptr); // Вывод адреса переменной x
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚Базу Знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Значимые типы обычно хранятся на стеке, когда они объявлены внутри метода. Это происходит потому, что стек обеспечивает быстрый доступ и автоматическое управление памятью.
void MyMethod()
{
int localVar = 10; // localVar хранится на стеке
}
Значимые типы могут храниться в куче, если они являются частью объекта ссылочного типа. Например, если структура или переменная типа
int является полем класса, то она будет храниться в куче вместе с объектом класса.class MyClass
{
public int Number; // Number хранится в куче, потому что MyClass - ссылочный тип
}
MyClass obj = new MyClass();
obj.Number = 42;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Существует два способа избежать упаковки и распаковки (boxing и unboxing) значимых типов при их хранении в коллекциях или использовании в других ситуациях, где тип данных не должен быть упакован в объект.
Обобщения позволяют создавать коллекции и методы, которые работают с любыми типами данных без необходимости упаковки.
// Пример использования обобщённого списка для значимого типа int
List<int> numbers = new List<int>();
numbers.Add(10); // Добавление без упаковки
int number = numbers[0]; // Чтение без распаковки
В некоторых случаях для избежания упаковки можно создать специальные структуры, которые содержат необходимые данные и методы.
// Обобщённый метод для работы с любыми типами данных без упаковки
public T FindMax<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}
// Использование метода для значимого типа int
int max = FindMax(3, 5);
Console.WriteLine(max); // Выведет: 5
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤1🤔1
Чем отличается метод Equal от ==? Equals проверяет логическое равенство объектов, а == сравнивает ссылки для объектов и значения для примитивов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥1
string является ссылочным типом, хотя по поведению он похож на значимый тип. Это означает, что переменная типа string содержит ссылку на объект строки, хранящийся в памяти, а не непосредственно данные.Объекты типа
string неизменяемы. Это означает, что после создания строки её содержимое нельзя изменить. Любые операции, которые кажутся изменяющими строку (например, Replace, Substring), на самом деле создают новую строку. string original = "Hello";
string modified = original.Replace('H', 'J'); // Создаётся новая строка "Jello"
string поддерживает различные операторы и методы для работы с текстом. Например, оператор + для конкатенации строк, метод Substring для извлечения подстрок, метод Split для разбиения строки и т.д. string hello = "Hello";
string world = "World";
string concatenated = hello + " " + world; // "Hello World"
Для оптимизации памяти строки могут интернироваться. Это означает, что строки с одинаковым содержимым могут храниться в единственном экземпляре в пуле строк.
string a = "test";
string b = "test";
bool areEqual = object.ReferenceEquals(a, b); // True, потому что строки интернированы
string имеет специальную поддержку на уровне языка. Например, строковые литералы в коде автоматически рассматриваются как объекты типа string. string greeting = "Hello, world!";
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Сравнение содержимого объектов классов в C# можно выполнить несколькими способами. Наиболее распространенные методы включают переопределение методов
Equals и GetHashCode, а также реализацию интерфейса IEquatable<T> и использование библиотек для глубокого сравнения. Для сравнения содержимого классов можно переопределить методы
Equals и GetHashCode. Это позволяет определить логику сравнения объектов на основе их полей. public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
Person other = (Person)obj;
return Name == other.Name && Age == other.Age;
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}
Позволяет улучшить производительность сравнения и сделать код более читаемым.
public class Person : IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
public bool Equals(Person other)
{
if (other == null)
return false;
return Name == other.Name && Age == other.Age;
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
return Equals((Person)obj);
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}
Существуют библиотеки, такие как
DeepEqual или Json.NET, которые позволяют выполнять глубокое сравнение объектов, автоматически сравнивая все их поля и свойства. using KellermanSoftware.CompareNetObjects;
public class Program
{
public static void Main()
{
Person person1 = new Person { Name = "Alice", Age = 30 };
Person person2 = new Person { Name = "Alice", Age = 30 };
var compareLogic = new CompareLogic();
ComparisonResult result = compareLogic.Compare(person1, person2);
Console.WriteLine(result.AreEqual); // True
}
}
Ещё один способ сравнить содержимое объектов - это сериализовать их в JSON и затем сравнить полученные строки.
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
Person person1 = new Person { Name = "Alice", Age = 30 };
Person person2 = new Person { Name = "Alice", Age = 30 };
string json1 = JsonConvert.SerializeObject(person1);
string json2 = JsonConvert.SerializeObject(person2);
bool areEqual = json1 == json2;
Console.WriteLine(areEqual); // True
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥1👾1
Классы и структуры обладают рядом различий, которые влияют на их использование и поведение в коде.
Классы: являются ссылочными типами (reference types). Переменные класса хранят ссылки на объекты, которые размещены в куче (heap).
Структуры: являются значимыми типами (value types). Переменные структуры хранят сами данные, и эти данные размещаются на стеке (stack) или в куче, если структура является частью объекта класса.
Классы: при передаче объекта класса по значению (например, в метод) передается ссылка на объект, а не сам объект.
Структуры: при передаче структуры по значению передается копия всех данных структуры.
Классы: могут иметь конструкторы по умолчанию и деструкторы. Класс может иметь инициализатор (конструктор), который задает начальные значения полей.
Структуры: не могут иметь явных конструкторов по умолчанию (без параметров). Все поля структуры должны быть инициализированы перед использованием, инициализация происходит автоматически.
Классы: поддерживают наследование (можно наследоваться от другого класса и реализовывать интерфейсы).
Структуры: не поддерживают наследование от других структур или классов, но могут реализовывать интерфейсы.
Классы: из-за размещения в куче и необходимости сборки мусора (garbage collection) могут быть медленнее при частом создании и удалении объектов.
Структуры: часто эффективнее по памяти и времени выполнения для небольших объектов, которые создаются и уничтожаются часто, благодаря размещению на стеке.
Классы: поддерживают полиморфизм, виртуальные методы, события и делегаты.
Структуры: обычно применяются для небольших, неизменяемых объектов. Не могут содержать деструкторы и не поддерживают наследование, кроме интерфейсов.
Класса
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
Структуры
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍5❤3