#c# #.net-core #asp.net-core-webapi
Вопрос:
Я использую api .net core 5. Чего я хочу добиться, так это заполнить объект на основе строки запроса. Затем, когда этот объект заполнен, я хочу ввести этот объект в классы, которым нужна эта информация.
То, как я сделал это сейчас, заключается в создании класса, и я зарегистрировал этот класс как одноэлементный.
Затем я создал некоторое промежуточное программное обеспечение, которое считывает строку запроса, получает зарегистрированный синглтон и устанавливает его значения:
public class SetDataMiddleware
{
private readonly RequestDelegate _next;
public SetDataMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Query.ContainsKey("slug"))
SetValues(context);
await _next(context);
}
private void SetValues(HttpContext context)
{
var slugValue = context.Request.Query["slug"];
var objectWithValues = (ValuesObject)context.RequestServices.GetService(typeof(ValuesObject));
var dataGetter = (IGetDataBySlug)context.RequestServices.GetService(typeof(IGetDataBySlug));
var retreivedData = dataGetter.Get(slugValue);
objectWithValues.Address = new Address
{
City = retreivedData.Address.City,
Street = retreivedData.Address.Street,
Zipcode = retreivedData.Address.Zipcode,
};
}
}
Затем я могу вводить ValuesObject
везде, где я хочу получить доступ к его значениям.
Хотя это работает нормально, мне было интересно, есть ли лучший, может быть, более аккуратный способ добиться того же самого.
Ответ №1:
Вы можете сделать это при регистрации объекта. Как говорят кодекастеры, не реализуйте синглтон, а область действия или переходный процесс.
services.AddScoped<IAddress, Address>(x =>
{
var context = services.BuildServiceProvider().GetRequiredService<IHttpContextAccessor>().HttpContext;
var slugValue = context.Request.Query["slug"];
var objectWithValues = (ValuesObject)context.RequestServices.GetService(typeof(ValuesObject));
var dataGetter = (IGetDataBySlug)context.RequestServices.GetService(typeof(IGetDataBySlug));
var retreivedData = dataGetter.Get(slugValue);
return new Address
{
City = retreivedData.Address.City,
Street = retreivedData.Address.Street,
Zipcode = retreivedData.Address.Zipcode,
};
});
Комментарии:
1. Спасибо. Как вы думаете, это хороший способ заполнения объекта, чтобы его можно было вводить везде? Или вы думаете, что есть лучший подход?
2. Это, на мой взгляд, лучшая версия. Также потому, что это просто понять и легко исправить.
3. Хорошо, большое спасибо 🙂
Ответ №2:
Это не работает нормально, синглтон разделяется между запросами. Два пользователя, одновременно посещающие страницу со слизняком, заставят одного увидеть значения другого. Просто поместите это в пункты контекста, это относится к одному запросу.
Затем в вашем контроллере, доступ HttpContext.Items
.
Комментарии:
1. Хм, действительно, ты прав. Но в основном этот объект не используется в контроллерах, я использую его в отдельных классах. Есть какие-нибудь мысли о том, как это сделать?
2. Да, я пропустил это, см. Ответ @Den.