locked
Instrumentation Profiler in CoreCLR(.Net Core) - Ways to get HttpContext in .NetStandard assembly RRS feed

  • Question

  • User1961932497 posted

    I am trying to Instrument .NET Core web applications that runs on .NET Core 3.1 using CoreCLR Profiler.
    When I allow injecting the code into the Web application's method the helper assembly(.NET standard 2.0) is got attached to dotnet.exe process and it is getting callbacks to the helper assembly.
    I have created helper assembly(.NET standard 2.0) with the injected functions body.

    Now I need to get the HttpContext.Current of the each HTTP request of .NET core web application in helper assembly(.NET standard 2.0). In .Net framework we have System.Web.HttpContext.Current and System.Web.HttpRequest to get the Header,cookie,session id and site name of each request. How can I achieve same in .Net standard? 

    1. Can I use Microsoft.AspNetCore.Http.HttpRequest in .NET standard 2.0 assembly? If so how can I add reference to .Net standard assembly?
    2. How can I get Header,cookie,session id and site name of .net core web application in .NET standard 2.0 assembly?
    3. What is the alternative/equivalent of following .Net Framework namespaces in .Net Core/.Net 
         A. System.Web.HttpContext.Current
         B. System.Web.HttpRequest
         C. System.Web.HttpCookie
         D. System.Web.Hosting.HostingEnvironment.SiteName

    It would be much helpful if i get some correct direction to get or use HttpContext.Current in .NetStandard assembly.

    Thanks in advance. 

    Thursday, March 12, 2020 12:52 PM

All replies

  • User475983607 posted

    The standard approach is ASP.NET Core Dependency Injection and/or middleware.  Please see the ASP.NET Core fundamentals documentation. 

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.1

    Thursday, March 12, 2020 1:18 PM
  • User-474980206 posted

    the code to implement HttpContext.Current (and its variants) in an async pipleined application is very expensive in performance. it meant a storage context needed to be setup for every async call, and for return from an async call. For this reason it was dropped from asp.net core which was designed for performance.

    there is no practical way to implement .Current in asp.net core or use it from a .netstandard library. you will need to create an instance of the profiling tool for each request, and pass the context or request to the instance, preferably in the constructor. asp.net core has middleware which will add the context as a service (DI) at the scope level. this allows asp.net core middle to access the context, which it would pass to your profiler.

    Thursday, March 12, 2020 2:30 PM
  • User1961932497 posted

    Thanks for your information.

    I went through ASP.NET Core Dependency Injection and Middleware.

    To get HttpContext of .NET Core web applications in .NET Standard class library I did following changes manually.

    • Services should be registered in the .NET Core app's Startup.ConfigureServices method.

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    • .NET standard middleware component should be added in the .NET Core app's Startup.Configure method.

            app.UseMiddleware<DotNetCoreProfiler>();  //where DotNetCoreProfiler is my .NET standard class

        // to use  my .NET standard class in .netcore application i need to add .netstandard .csproj as reference to the .netcore app .csproj   

       //  <ProjectReference Include="..\..\source\CoreClrHelperAssembly\CoreClrHelperAssembly.csproj" />                                                                                 

    • Need to create a public constructor in .NET Standard class  with RequestDelegate object as argument                                                                                                                     
      public DotNetCoreProfiler(RequestDelegate next)
      {
      next = next;
      }
    • Need to add Task method in .NET Standard class

          public async Task Invoke(HttpContext httpContext){  }                                                                                                                                                                                                            

    After doing above changes (i.e changes in both .NET Core web application and .NET Standard library), if i ran my .NET Core web application I am getting HttpContext in .NET Standard library. Please correct me if i missed anything here to get HTTP context? 

    Can you please help me to do above changes in run time in coreclr profiler.

    A) How can I register  HttpContextAccessor service in the app's Startup.ConfigureServices method through coreclr profiler?

    B) How can I call .NET standard middleware component in the app's Startup.Configure method without adding .netstandard .csproj as a reference to .netcore application? Can I add this middleware in my .netstandard assembly once i got callback to .netstandrad assembly? If so how can i do this?

    The above changes i did manually for understanding middleware and DI.Can you please direct me to do these things at run time in .NET Standard library?

    Note that I am monitoring .Net core web application through coreclr profiler and getting callbacks to .NET Stanrd assembly by rewriting IL code. Now I need to get Httpcontext along with that callback methods.

    Thanks in advance. 

    Friday, March 13, 2020 3:15 PM
  • User-474980206 posted

    asp.net core middleware is typically not written as a .netstandard library (it can call .netstandard). You can but you need to reference all the asp.net core abstract classes used by middleware. assuming you are using 3+, change the library project:

       <TargetFramework>netcoreapp3.0</TargetFramework>
       <ItemGroup>
          <FrameworkReference Include="Microsoft.AspNetCore.App"></FrameworkReference>
       </ItemGroup>
    

    if your intent is share between 4.* and core, make a .netstandard 2.0 that does the logging, and write a wrapper for core and one for 4.8 that calls the library. 

    Friday, March 13, 2020 4:54 PM
  • User1961932497 posted

    Hi Bruce,

    I have already did the changes you mentioned in above post. Now I struck to get Http context at run time in Helper assembly (.NET Standard library).

    A) How can I register HttpContextAccessor service in the app's Startup.ConfigureServices method through coreclr profiler?

    B) How can I call .NET standard middleware component in the app's Startup.Configure method without adding .NET Standard .csproj as a reference to .NET Core application? Can I add this middleware in my .NET Standard assembly once i got callback to .NET Standard assembly? If so how can i do this?

    Can you please direct me to do get Httpcontext at run time in .NET Standard library?

    Note that I am monitoring .Net core web application through coreclr profiler and getting callbacks to .NET Standard assembly by rewriting IL code. Now I need to get Httpcontext along with that callback methods.

    How can I get HTTP context by rewriting IL in coreclr profiler by getting callbacks to .NET Standard library? 

    Monday, March 16, 2020 4:39 AM
  • User-474980206 posted

    for middleware to access httpcontext, just use DI:

    public async Task InvokeAsync(HttpContext context)
    {
          // use context
          
          // Call the next delegate/middleware in the pipeline
          await _next(context);
    }

    you don't call middleware in startup, you just register it:

      services.AddSingleton<IMyMiddlewareInterface>(new MyMiddleware())

    if the middleware is in its own project (as it should be), you just add a project reference to the asp.net core project.

    I don't understand your references to .netstandard and .netstandard library. I assume you are calling a .netstandard library from the asp.net core middleware proj. if you need a define httpcontext  in a .net standard library it is in nuget package

        Microsoft.AspNetCore.Http.Abstractions

    you must understand that HttpContext is an instance object tired to a request scope. that means there is one created of each request, as async requests share the same thread, the context is only passed as a method parameter (stack). any profiled method using HttpContext will have it passed as a parameter.

    also note that in asp.net core there are no app domains as app domain support was not implemented.

    while you could callback into middleware, the callback can not access the HttpContext or any request information as it only lives the InvokeAsync() method. don't try to copy HttpContext to a private in the middleware as it will be invalid. there can be several InvokeAsync each with its own HttpContext running at the same time.

    Monday, March 16, 2020 7:11 PM
  • User1961932497 posted

    Hi Bruce,

    As you mentioned in previous post,Httpcontext is request specific and it will be lives only in InvokeAsync() method. And for middlewar to access HttpContext need to use DI. 

    I have ASP .NET core web/MVC  application and if I give request to that website, that web application will be executed.

    In CoreClr profiler, I am rewriting IL of that web application and Injecting some user defined method calls. And that user defined method calls are defined in separate  .NET Standard library module. And this .NET Standard module is  loaded in to web application process and it is getting callbacks.

    So now I need Httpcontext of each request of ASP .NET core application in .NET Standard library module. 

    To get Httpcontext of ASP .NET core web application, we have DI and middle ware.

    • To implement DI in coreclr profiler to get Httpcontext of ASP .Net core web application in .NET Standard library,I need to register  my own service in Startup.ConfigureServices() of ASP .net core web application.  

             How can I register my service that is defined in the .NET standard library in ASP .NET Core web application through coreclr profiler? 

                services.AddSingleton<IMyDependency, MyDependency>()

    • To Implement Middleware in coreclr profiler to get Httpcontext of ASP .Netcore web application in .NET Standard assembly, I need to create my own new middleware in .NET Standard library and that new middleware need to to get call back from the .NET core web application. which method callback of .NET core web application will give Httpcontext in my new middleware?

    The  InvokeAsync() method only has Httpcontext and how can i get this information in .NET standard library?

    Please provide me the clue/steps to get Httpcontext of ASP .Net core web application in .NET Standard library. Which .NET core web application method callback has Httpcontext and how can i get it .Net Standard application by MIddleware.

    I Need to access Httpcontext  of each request of .NET core website in .NET Standard assembly.

    • if the middleware is in its own project (as it should be), you just add a project reference to the asp.net core project.

            I have middleware in .NET Standard assembly and how can i add this as reference to .net core web application though coreclr profiler ?

    To do DI or middleware implementations in .NET Standard assembly methods those are called from the ASP .NET core web application what and all required from the ASP .NET core web application to get Httpcontext? Do I need any object or any method parameters of .NET core web application in .NET Standard library to get Httpcontext?

      

    Wednesday, March 25, 2020 12:32 PM
  • User-474980206 posted

    a singleton can not get access to a httpcontext because httpcontext is scope based. you need to pass the httpcontext to any callback in the singleton.

    asp.net core is async, this means it allows multiple requests on the same thread. this means there are multiple httpcontexts for the same thread. the middleware pipeline passes the httpcontext to all the middleware actions. DI scoped objects are created at the start of the pipeline, and available to pipeline calls. 

    the middleware support (services) is only available via pipeline calls (or objects the pipeline creates like controllers). 

    while you can implement DI in .netstandard library (see services) this would be a new scope and could not access HttpContext which is in the pipeline scope. 

    again HttpContext is not available in .netstandard. you will need to use the abstractions NuGet package. while its possible to build a middleware call in a .netstandard library, you will need to reference all the required abstraction nuget packages. 

     again there is no way to implement HttpContext.Current in asp.net core (get the context via a static). the context must passed to the caller. 

    Wednesday, March 25, 2020 3:14 PM