How to reload AWS options at runtime - c#

I am running an ASP.NET Core MVC app in a docker container, with an AWS credentials file. I have another service that is putting new keys into the file when the old ones expire, but these new keys don't seem to propagate through to my MVC app and my site crashes. I have seen that normally the solution to get strongly typed configuration to reload is to use IOptionsSnapshot, like:
services.AddDefaultAWSOptions(Configuration.GetAWSOptions())
.AddScoped(config => config.GetService<IOptionsSnapshot<AWSOptions>>().Value)
.AddAWSService<IAmazonS3>();
but this gives an exception:
System.InvalidOperationException: Cannot resolve scoped service 'Amazon.Extensions.NETCore.Setup.AWSOptions' from root provider.
Does anyone have a solution to getting ASP to reload the AWS credentials file? I'd like to continue using the AWS dependency injection extension if possible.

By default, AddAWSService registers the client factory in singleton scope, which means it's one and done for the life of the application. However, AddAWSService has a lifetime param you can utilize to customize this. Essentially, you need a shorter lifetime on the client, so that it will be recreated with the new settings. You can choose either "scoped" (request-scoped) or "transient" (new instance every time it's injected).
Obviously with "scoped", you'll get a connection with the updated settings every request. However, if you do any further operations on the same request after the settings have been changed, it will remain the old connection with the old settings (i.e. you'll still have the same issue, at least for the life of the request).
Using "transient" scope, you'll have have a client with the most updated settings, but you'll end up basically with a client for every use, which may not be ideal.

Related

How to reload configuration in OpenIdDict?

I'm using instrospection (OpenIdDict v3.1.1) and have 1 application which can work in 2 modes:
standalone mode,
proxy mode - current instance (proxy) forwards request to second instance (master).
In my scenario master instance can be unavailable and then proxy doesn't forward requests to master but execute them internally. Because of it I have to change Issuer in validation options. The problem is that changes don't apply on internal work of openIdDict, I tried to do it by change IOptions. It tries to send request to master instance all the time.
Currently I see only one solution of this problem, restart whole application and set proper issuer on the start of the application. The best solution for me it's reloading configuration in runtime without restart.

How to do DI for non-request bound code in ASP.NET Core?

We're all being taught to use Dependency-Injection for coding in ASP.NET Core applications, but all of the examples I've seen so far that related to the retrieval of services via DI relate to situations where the method that has the service reference injected is strictly bound to a specific HTTP request (HttpContext) (e.g. MVC controllers, Routing delegates).
Service location is warned against as an anti-pattern, but I'm not sure on how to obtain a proper service (e.g. DbContext) reference via DI in code that is not bound a specific HTTP request, e.g. code that has to respond to messages arriving over a websocket.
Although the websocket itself is set-up initially with a specific HTTP request, messages will get responses over potentially a long lifetime of the websocket (as long as the user web session lasts). The server should not reserve/waste a DbContext/DB connection over this entire lifetime (this would result in exhaustion quickly), but rather obtain a DB connection temporarily when a message arrives and requires a response; discarding the DbContext/connection immediately afterwards - while the original HTTP request that set-up the websocket in the very beginning of the user-session technically is still there.
I haven't been able to find anything else but using:
httpContext.RequestServices.GetService(typeof(<MyNeededDbContext>)
This way I use the initial httpContext (obtained via DI when the websocket was set up), but at multiple times after that whenever a websocket message needs a response I can request a transient service object (a DbContext in this example), that may be recycled or pooled after the message response is complete, but while the original httpContext is very much still alive.
Anyone aware of a better approach?
You can create a new service scope to manage the lifetime of services yourself;
IServiceProvider provider = ...;
using (var scope = provider.CreateScope())
{
var context = scope.ServiceProvider.GetService<MyNeededDbContext>();
...
}

Google Datastore authentication issue - C#

I'm trying to connect to the Google Datastore on my account with service account credentials file (which I've created according to the documentation), but I'm encountering with authentication error while trying to insert an entity:
Grpc.Core.RpcException: Status(StatusCode=Unauthenticated,
Detail="Exception occured in metadata credentials plugin.")
My code is:
var db = DatastoreDb.Create("myprojectid");
Entity entity = new Entity{
Key = db.CreateKeyFactory("mykindname").CreateIncompleteKey()
};
var keys = await db.InsertAsync(new[] { entity });
The GOOGLE_APPLICATION_CREDENTIALS variable refers to the credentials file and when calling GoogleCredential.GetApplicationDefaultAsync() to see if the credentials object is valid it indeed looks good...
I saw some earlier examples which used the GetApplicationDefaultAsync function togehether with some DatastoreService object - but I couldn't find the DatastoreService object (probably it was there in old versions...) in the latest .Net API: Google.Cloud.Datastore.V1
Notice that I don't want to use the other authenticaiton methods:
1) Using the gcloud cli.
2) Running from Google environment (app engine for example).
Any idea how to solve this?
After the great help of Jon Skeet the issue was solved.
The authentication issues can occur if you don't reference all the required Datastore dlls. Make sure that all the dlls are referenced on the project that are running the calls to the Datastore.
I've added the Google Datastore lib via the NuGet to my test project and everything worked!
Notice that in such cases it is recommended to enable gRPC logging. `(For exmaple: GrpcEnvironment.SetLogger(new ConsoleLogger()), there you'll probably see if there were issues loading several dlls...
Authentication can be broken if your system clock is significantly incorrect. Check your system time, and fix it if necessary, then try authenticating against Datastore again.

Is there a way I could set context for a session (ie, one call to my API) and not for the entire app domain? (ASP.NET)

I have created a large application and I have now run into a problem.
I have separated customers by virdirs so they have always been in different application pools. I took advantage of this and set static variables for db connection string and other context stuff on session_start and had it available to me throughout my app.
Now I have been overloaded with the amount of virdirs I have had to create (over 500 and quickly growing) and I feel I need to move these to one (or several) application pools. The problem is I don't pass the "session context" I get from the URL, throughout the app. Changing to the app to pass the context down would basically mean I would need to rewrite the app.
Is there a way I could set this context for a session (ie, one call to my API) and not for the entire app domain? Your help is greatly appreciated!
context example
- db con str
- customer log folder
EDIT: I was thinking I could maybe have a table that links the context information to the thread id (System.Threading.Thread.CurrentThread.ManagedThreadId)?
What do you mean by 'context'? Do you mean the request/response/session information? You do not need to pass them manually. For the duration of processing of a http request, the ASP.Net framework exposes all that in a static way:
var ctx = System.Web.HttpContext.Current;
var req = ctx.Request;
var rsp = ctx.Response;
var sess = ctx.Session;
var cache = ctx.Cache;
var myOtherFoos = ctx.Items;
In an ASP.Net application, you can access the static Current-Context from just anywhere, provided you have added the reference to System.Web assembly.
If you do not mean that "context", but if you mean some your own additional information that you need to pass along with the request-processing, then the Items of HttpContext is just for that! It is a fresh collection created at each new request and you can use it as a lightweight scratchpad to keep your things during single-request processing. Unlike Cache or Session, the "Items" evaporate at the moment the request processing ends, so there's no worry about leaks or mixing data with other requests. Just be careful in what keys you pick, try to not collide with the framework thingies that sit there :)

Custom SharePoint 2010 WCF Service - How to set MaxReceivedMessageSize parameter

I have developped a custom WCF Web Service within a SharePoint 2010 Visual Studio empty project.
My web service is working well. The problem is related to the size of the request I can send to this web service. I have realized that is something around 300Kb. If I go bigger than that, the service/client is sending me an exception.
I've looked around on the web and see that the MaxReceivedMessageSize setting may be my solution. I've tried using a FeatureActivated method to set this information using this kind of request:
// increase maximum size of requests to this web service: http://msdn.microsoft.com/en-us/library/ff599489.aspx
SPWebService contentService = SPWebService.ContentService;
contentService.ClientRequestServiceSettings.MaxReceivedMessageSize = -1;
SPWcfServiceSettings csomWcfSettings = new SPWcfServiceSettings();
csomWcfSettings.MaxReceivedMessageSize = 10485760; // 10MB
contentService.WcfServiceSettings["PT-SP-P2S-DocumentCreator.svc"] = csomWcfSettings;
contentService.Update(); // access denied thrown here!
With that code, I have an Access denied (I'm actually the Site Collection Administrator).
I also know that this parameter may be set in the app.config of web service host but, in SharePoint, where to I need to change this parameter.
I think you should make this change in the web.config file of the Web Application in which the feature is activated. SharePoint provides APIs to make web.config changes. In fact, using APIs to make changes to your web.config is preferred option because SharePoint uses Timer Job and makes same updates to all Web Front End servers in your environment. There are 2 ways to make changes to web.config as described here:
http://msdn.microsoft.com/en-us/library/ms460914.aspx
In your case, since you want to make the change only when your feature is activated, you would take the API approach as documented here: http://msdn.microsoft.com/en-us/library/bb861909.aspx

Categories