Home > Enterprise >  What is the best way to set a filled object that can be injected?
What is the best way to set a filled object that can be injected?

Time:10-21

I am using .net core api 5. What I want to achieve is to fill an object based on the query string. Then, when this object is filled, I want to inject this object into classes that needs that info.

The way I have done it now, is by creating a class and I have this class registered as a singleton.

Next, I have created some middleware that reads the query string, gets the registered singleton and set it's values:

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,
        };
    }
}

Next I can inject ValuesObject everywhere where I want to access it's values.

Although this works fine, I was wondering whether there's a better, maybe a more neat way to achieve the same thing.

CodePudding user response:

You can do it when register the object. How CodeCaster say, not implement singleton but Scoped or Transient.

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,
                };

            });

CodePudding user response:

This doesn't work fine, a singleton gets shared between requests. Two users visiting a page with a slug simultaneously will cause one to see the other's values. Just put it in the context's items, this belongs to one request.

Then in your controller, access HttpContext.Items.

  • Related