locked
Using HttpContext in a class and calling a class method in controller action RRS feed

  • Question

  • User206383436 posted

    Hello,

    I am writing my very first ASP.NET Core 2.2 web application.

    I am trying to use HttpContext in a class library following instructions provided here: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-2.2#use-httpcontext-from-custom-components

    This is my class which compiles correctly:

        public class Utilities
        {
            //IHostingEnvironment _hostingEnvironment;
            IHttpContextAccessor _httpContextAccessor;
    
            // *********************************************************************************************
            //                  Constructor.
            // *********************************************************************************************
            //public Utilities(IHostingEnvironment hostingEnvironment, IHttpContextAccessor httpContextAccessor)
            public Utilities(IHttpContextAccessor httpContextAccessor)
            {
                //_hostingEnvironment = hostingEnvironment;
                _httpContextAccessor = httpContextAccessor;
            }
    
            // *********************************************************************************************
            //                  System event is generated.
            // *********************************************************************************************
            public void AddSystemEvent(string exceptionMessage, string exceptionType, string exceptionStack)
            {
                // System events location directory.
                //string eventsDirectory = Path.Combine(@"c:\Temp\Eventos\");
                string eventsDirectory = @"c:\Temp\Eventos\";
    
                // Name of file where event will be saved.
                string eventsFile = "";
                eventsFile += DateTime.Now.Year.ToString() +
                    '-' + DateTime.Now.Month.ToString().PadLeft(2, '0') +
                    '-' + DateTime.Now.Day.ToString().PadLeft(2, '0') +
                    ".log";
    
                // System event is generated.
                StreamWriter eventsStreamFile = new StreamWriter(eventsDirectory + eventsFile, true);
                eventsStreamFile.Write(new PgSqlTimeStamp(DateTime.Now).ToString("yyyy/MM/dd HH24:MI:SS AD") + "\t");
                eventsStreamFile.Write(_httpContextAccessor.HttpContext.User.Identity.Name + "\t");
                eventsStreamFile.Write(exceptionMessage + "\t");
                eventsStreamFile.Write(exceptionType + "\t");
                eventsStreamFile.Write(exceptionStack);
                eventsStreamFile.WriteLine("");
                eventsStreamFile.WriteLine("");
                eventsStreamFile.Close();
            }
        }

    In my project I have modified the ConfigureServices method in startup.cs file as follows (please see the last 3 lines):

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });
    
        services.AddDbContext<ApplicationDbContext>(options =>
                    options.UsePostgreSql(Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>()
            .AddDefaultUI(UIFramework.Bootstrap4)
            .AddEntityFrameworkStores<ApplicationDbContext>();
    
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        services.AddHttpContextAccessor();
        services.AddTransient<Utilities>();
    }

    And finally, this is my controller (please see private variable at the beginning and EventoSistema action at the end):

        public class HomeController : Controller
        {
            private Utilities _utilities;
    public IActionResult Index() { return View(); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } public IActionResult Prueba() { return View(); } public IActionResult EventoSistema(Utilities utilities) { _utilities = utilities; _utilities.AddSystemEvent("Exception message", "Exception type", "Exception stack"); return View(); } }

    When I run the application I get the following error:

    An unhandled exception occurred while processing the request.

    InvalidOperationException: Could not create an instance of type 'Elisur.Tools.Utilities'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'utilities' parameter a non-null default value.

    Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext)

    The instructions provided in the link I mention at the very top of this post only provides information about the ConfigureServices method and the class itself so my problem is about how to call my method (AddSytemEvent) that belongs to my class (Utilities) from the controller.

    I will very much appreciate your feedback.

    Respectfully,
    Jorge Maldonado

    Wednesday, September 18, 2019 5:54 PM

Answers

  • User-474980206 posted

    you use DI to add the utility to the controller via its constructor:

    public HomeController (Utilities utilities)
    {
        _utilities = utilities;
    }  

    not sure what this action is supposed to do, but you don't pass the Utilities instance. try:

            public IActionResult EventoSistema()
            {
                _utilities.AddSystemEvent("Exception message", "Exception type", "Exception stack");
                return View();
            }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, September 19, 2019 12:11 AM

All replies

  • User-474980206 posted

    you use DI to add the utility to the controller via its constructor:

    public HomeController (Utilities utilities)
    {
        _utilities = utilities;
    }  

    not sure what this action is supposed to do, but you don't pass the Utilities instance. try:

            public IActionResult EventoSistema()
            {
                _utilities.AddSystemEvent("Exception message", "Exception type", "Exception stack");
                return View();
            }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, September 19, 2019 12:11 AM
  • User206383436 posted

    Oh yes, you are perfectly right Bruce. It makes sense. Constructors are the key.
    My issue is now solved.
    I appreciate your kind support.

    Best regards,
    Jorge Maldonado

    Thursday, September 19, 2019 2:22 PM