Where is Application Insights injecting HttpContext into IHttpContextAccessor.Request? - azure

I've found myself in an interesting position. I currently use the latest Unity container, I'm on asp.net core 2.2, and I use application insights. As such, I have configured DI in my web app to use unity instead of the out of the box DI provider in core. I also use Application Insights and use the IWebHostBuilder.UseApplicationInsights extension to spin up AI for my app.
With all this in mind, I have a piece of code whose constructor takes in IHttpContextAccessor so I can access the HttpContext. It was working great. Then, I had another small app that I was trying to reuse the functionality, and the HttpContext was null coming from IHttpContextAccessor. With a bunch of guess, test, revise, I found that IWebHostBuilder.UseApplicationInsights seems to initialize that Request property (HttpContext) on IHttpContextAccessor. If I commented out that AI extension, I would get null; uncomment it, it worked.
I've started to look through the AI code to figure out what exactly they're doing, but honestly, with all the dependencies and pipelines and all that, it's a pretty daunting task. I was hoping someone could point out where/how AI is doing this so my code doesn't NEED AI in order to work. All help would be incredibly awesome.

Use AddHttpContextAccessor extension to add it to DI. HttpContextAccessor is not added by default due to performance impact.
services.AddHttpContextAccessor();

After some struggle, and hoping this post would enlighten me on the AI ask, I found that I didn't need to replicate the AI mechanism, if there's even one at all.
Originally, I was accessing the IHttpContextAccessor via code in the view (Razor). I have an abstract factory pattern I was using to instantiate IHttpContextAccessor via Unity (this pattern came over from my .Net Frame work days). Once I moved that code back to the controller and used proper .net core DI to get the dependency via the constructor, everything started working.
There must be something there I'm missing, but I have the code working so I'm happy. If someone could shed light on why one way works vs the other, I'd be happy to hear it.

When you enable application insights by calling .UseApplicationInsights(), it adds HttpContextAccessor. There are many components in ApplicationInsights which require HttpContextAccessor injected to it. eg: ClientIpHeaderTelemetryInitializer.
This is the exact line where this is occuring:
https://github.com/Microsoft/ApplicationInsights-aspnetcore/blob/develop/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs#L137

Related

Custom TelemetryInitializers in AzureFunctions

Short: Is there any way to add a custom ITelemetryInitializer to an AzureFunction application?
Long:
After successfully integrating our AzureFunction application with ApplicationInsights and thoroughly instrumenting our code, it became evident really quickly that we'd need to correlate the various Trace and Request telemetry together. To do this we wanted to reuse a custom property we write to all trace logs called a SessionId.
A quick search yielded this SO post and this Docs article. The problem is that these articles assume I have access to some startup event or to the ApplicationInsights.config file on the server. I could be wrong but I don't believe I have access to either one of these.
So my question is, how do I do this with AzureFunctions?
No, it's not possible to customize that. There is work in progress to allow that, but it's not there yet.
You can see more details on these Github issues
application insights integration - ITelemetryInitializer doesn't have any effects #1416
Unable to access TelemetryConfiguration in DefaultTelemetryClientFactory (App Insights) #1556
EDIT:
It's possible in azure function v2.
There was a question on stackoverflow with problem here:
Custom Application Insight TelemetryInitializer using Azure Function v2
The problem was solved and from version Microsoft.Net.Sdk.Functions 1.0.25 all works fine, more here:
https://github.com/Azure/azure-functions-host/issues/3731#issuecomment-465252591
One abhorrent solution I came up with is to reflect into the ILogger that gets passed to the function to get at the ILogger array it hides inside. Then find the ApplicationInsightsLogger ILogger and reflect harder to pull out the TelemetryClient it uses. Once you get this you can merely set the SessionId property on the client's Context.
This works "great" however not only do I now have reflection in my code I had to downgrade the version of ApplicationInsights package I was using to get the type casting to stick.
Looking forward to better support in the future.

Unity container usage in UWP

I am trying to develop Prism 6 UWP Application .
My current problem is I want to register all objects used in Application with Unity Dependency injection container .
But so many UI objects are created by infrastructure(Activator.CreateInstance(type)) and no way to trigger their creation through dependency injection conatiner.I would be fine even if I register created objects with DI conatiner.
I refered Github sample application AdventureWorks.Shopper in Prism samples.
Here I saw views are created by infrastructure ,but some other objects are created by Dependency injection conatiner .
Is there any way to get all objects in applications and register them with DI conatiner ?
Is there any way to get all objects in applications and register them with DI container or trigger all creation through DI conatiner?
Generally you shouldn't try to have your UI objects created by the container, because as you mention, the XAML parsing process (infrastructure as you call it) is responsible for doing that and there is no easy way to get in the loop to take over that construction process.
This is one of the reasons we added the ViewModelLocator to Prism - so that from the ViewModel down through all of its dependencies, you can wire up the SetDefaultViewModelFactory method to use the container to do the construction of all your ViewModels and their dependencies (and their dependency's dependencies, etc.) as long as you use ViewModelLocator to wire the View to the ViewModel.
If you are following the MVVM pattern well, then there should almost never be a need to construct the UI objects themselves through the container because they should not be doing any logic in the code behind that would depend on things injected by the container. But that is not to say you will never need to do that. So for those situations where you need to do that You can either get to the container through the Application.Current as suggested by S Vasudev with some casting. Or if you need to do that a few places and don't want all that casting "noise" in the code, then write a simple helper object with a static property that you can set in the OnInitializeAsync method of the App class and then easily access anywhere.
If you are doing that in more than a few places you should start to question your design. And yes statics (globals) are evil and should be avoided whenever possible. But if it is just a few places in the code behind of a few views, sometimes you need to be a pragmatic programmer who gets things done and not an MVVM purist who overcomplicates things just to avoid a few minor violations of the MVVM guidance.
One way we found :-
You can access unity container like this :-
unityContainer = (UnityContainer)((Prism.Unity.Windows.PrismUnityApplication)Application.Current).Container;
In constructor of objects which are created by Activator.CreateInstance,we can use unity container and register that instance to unity container.
In that way , all objects gets registered with unity conatiner
example:-
unityContainer.RegisterInstance(this);

Application State / Test Fixtures with Xcode UI Tests

A pretty common problem with any kind of integration test is getting the unit under test into a known state -- the state that sets up well for the test you want to perform. With a unit test, there's usually not much state, and the only issue is in potentially mocking out interactions with other classes.
On the other hand, when testing a whole app there's all sorts of potentially persistent state, and getting the app into a clean state, or trickier still, into a known state that isn't "clean" without any access to the app itself is a little tricky.
The only suggestion I've found is to embed any necessary setup in the app, and use something like an environment variable to trigger setup. That is, of course, viable, but it's not ideal. I don't really want to embed test code and test data in my final application if I can avoid it.
And then there's mocking out interactions with remote services. Again you can embed code (or even a framework) to do that, and trigger it with an environment variable, but again I don't love the idea of embedding stubbing code into the final app.
Suggestions? I haven't been able to find much, which makes me wonder if no-one is using Xcode UI testing, or is only using it for incredibly simple apps that don't have these kinds of issues.
Unfortunately, the two suggestions you mentioned are the only ones that are possible with Xcode UI Testing in its current state.
There is, however, one thing you can do to mitigate the risk of embedding test code in your production app. With the help of a few compiler flags you can ensure the specific code is only built when running on the simulator.
#if (arch(i386) || arch(x86_64)) && os(iOS)
class SeededHTTPClient: HTTPClientProtocol {
/// ... //
}
#endif
I'm in the middle of building something to make this a little easier. I'll report back when its ready for use.
Regarding setting up the state on the target app there's a solution. Both the test runner app and your app can read and write to the simulator /Library/Caches folder. Knowing that you can bundle fixture data in your test bundle, copy it to the /Library/Caches on setUp() and pass a launch argument to your application to use that fixture data.
This only requires minimal changes to your app. You only need to prepare it to handle this argument at startup and copy over everything to your app container.
If you want to read more about this, or how you can do the same when running on the device, I've actually written a post on it.
Regarding isolating your UI tests from the network, I think the best solution is to embed a web server on your test bundle and have your app connect to it (again you can use a launch argument parameterize your app). You can use Embassy for that.

What is the role of the startup.cs file?

I was trying to explore some ASP.NET-5 applications where I found the startup.cs file. Where we set out routing and all (of course not only for routing). I also see some demo where has shown the use of dependency injection here. So, I'm looking for answers to the below questions:
Why this startup.cs is? What it does?
What are the uses of this file?
What is the advantages of this?
And is there any good documentation to know the use of startup.cs in details. And why the application does not work if we change the class name 'Startup' to something else?
I do have very elementary idea about OWIN and pipeline. Please help me to find these answers.
Just repeating here what it's said in Getting started with vNext
By default, the vNext hosting environment expects to find a startup class named Startup.
This class must contain a Configure method that takes an IBuilder parameter, and you configure the HTTP pipeline inside this Configure method. The empty project creates the class with nothing in the Configure method.
I would recommend you to take a look on vNext Moving Parts by Louis Dejardin since it explains a bit more about OWIN pipeline and vNext.
Sorry for not being of much help!

Web service client can not be created by jaxws:wsimport utility [binding.xsd]

I'm trying to consume a web service but I can't even start. I get an error as soon as I include the Web Service. I have researched and found similar errors but not this one. I hope you guys know a way around this:
I can't see the methods I should under Web Service References -> info, the 'info' appears with an X, see the image:
So I can't see the methods. A friend gave me his project and compiled it and got the same error, but it worked. I tried copy-pasting the methods into my project and it worked as well. The thing is how am I supposed to use the methods if I can't know them?
Thankyou in advance

Resources