Make use of services in StackExchange.Redis callback - stackexchange.redis

I was wondering if it is possible to make use of my services in my subscription callback. So something like this:
var redis = ConnectionMultiplexer.Connect("redis");
var sub = redis.GetSubscriber();
sub.Subscribe("profile:created").OnMessage(channelMessage => {
var profile = JsonConvert.DeserializeObject<Profile>(channelMessage.Message);
//In some way get the profile service
profileService.InsertProfile(profile)
})
The profile service is added as a scoped service in the startup like following:
services.AddScoped<IProfileService, ProfileService>();

Related

MassTransit riders Add ability to dynamically connect endpoints

I would like to configure Add bus rider dynamically into a class not into startup.
Working well with RabbitMQ.
But I don't know how to Add Rider to my bus.
private IBusControl ConfigureBus()
{
var massTransitSection = this.configuration.GetSection("MassTransit");
var url = massTransitSection.GetValue<string>("Url");
var host = massTransitSection.GetValue<string>("Host");
var userName = massTransitSection.GetValue<string>("UserName");
var password = massTransitSection.GetValue<string>("Password");
var busControl =
Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Host($"rabbitmq://{url}/{host}", configurator =>
{
configurator.Username(userName);
configurator.Password(password);
});
cfg.PublishTopology.BrokerTopologyOptions = PublishBrokerTopologyOptions.MaintainHierarchy;
});
busControl.StartAsync();
return busControl;
}
Thx a lot for your help
Riders cannot be connected after the bus has been configured. Topic endpoints are also not able to be connected after the bus has been configured.

How to implement versioning for Token endpoint in Web API 2

I have a Asp.Net Web API 2 using Token based authentication (OAuth2).
I have implemented Web API versioning using aspnet-api-versioning.
So now I have three different versions of my API. It's really great, I can now change V3 without affecting the current API.
But the /token endpoint is not versioned because it is not in my controller. It's in the Providers.
I searched but couldn't find anything helpful.
We can register more than one token endpoint in the Startup.Auth.cs
So here's what I did:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true, //Allow HTTP to send username password.
};
app.UseOAuthBearerTokens(OAuthOptions);
OAuthOptionsV3 = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/api/V3/Accounts/Token"),
Provider = new ApplicationOAuthProvider2(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true, //Allow HTTP to send username password.
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptionsV3);
So now I have different token endpoint for each version.
I'm not familiar with this particular setup, but this looks like middleware. There isn't quite enough information here to provide you with a specific answer, but your goals should be achievable in one of a few ways:
Option 1 - Use the Conventions API
If you authorization endpoint is actually a controller (though I think it is not), you can use the Conventions API like so:
services.AddApiVersioning(options =>
{
options.Conventions.Controller<OAuthController>().IsApiVersionNeutral();
}
Conventions was specifically meant to deal with a scenario where a controller might be externally defined and you don't have any control over the source code.
Option 2 - Use a Custom Convention
Middleware could create actions dynamically. As long as actions are actually produced, then you can use a custom IControllerConvention. You would be passed the ControllerModel which contains the actions you need to version. Assuming this is the correct behavior, you'd be looking for matching actions in the source model and then you can apply it to the controller conventions with something like:
public class MyConventions : IControllerConvention
{
public bool Apply(IControllerConventionBuilder controller, ControllerModel controllerModel)
{
var method = // TODO: resolve the target method from controllerModel
if (method == null)
{
return false;
}
controller.Action(method).IsApiVersionNeutral();
return false;
}
}
Option 3 - In Middleware
If this is pure middleware, API versioning isn't directly supported there. You can, however, support versioning on your own if the pipeline is composed properly. Specifically, API Versioning must come before other parts of middleware that need it. This usually happens automatically, but if you need to control registration, you need to change your setup to handle it manually like this:
services.AddApiVersioning(options => options.RegisterMiddleware = false);
// ... inside application setup
services.UseApiVersioning();
The API Versioning middleware doesn't really do much of anything special. It merely adds a pipeline feature. As long as that's before your other middleware, it will be available downstream like this:
var feature = context.Features.Get<IApiVersioningFeature>();
// the raw, unparsed API version, if any
var rawApiVersion = feature.RawApiVersion;
// the parse API version; will be null if no version is specified
// or the value cannot be parsed
var apiVersion = feature.ApiVersion;
// TODO: enforce versioning policies within the middleware
Option 4 - Use the API Explorer
If none of the previous approaches will work for you, you can leverage the API Explorer extensions for API Versioning to build your configuration (as above) from discovered APIs. This would have the advantage of not being hardcoded or require changes every time you release a new version.
Your application startup configuration would change to something like this:
public void Configure(IApplicationBuilder app, IApiVersionDescriptionProvider provider)
{
foreach (var description in provider.ApiVersionDescriptions)
{
var options = new OAuthAuthorizationServerOptions()
{
TokenEndpointPath = new PathString($"/api/{description.GroupName}/Accounts/Token"),
Provider = new ApplicationOAuthProvider2(PublicClientId),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(TokenExpirationInDays),
AllowInsecureHttp = true,
};
app.UseOAuthBearerTokens(options);
}
}

Updating graphql schema without a server restart in apollo 2

My project has a declarative way of defining schema and resolvers, which is maintained in a separate repository. My graphql server polls the result of this to look for updates to the schema.
Using apollo-server-express#1, I had direct access to the graphqlExpress middleware, so when the schema changed I could construct a new instance of it and throw away the old one, something like this
const { graphqlExpress } = require('apollo-server-express');
let api;
const constructAPI = () => {
try {
const newSchema = createSchema();
api = graphqlExpress(({ headers }) => ({
schema: newSchema,
}));
logger.info({ event: 'GRAPHQL_SCHEMA_UPDATED' });
};
schemaPoller.on('change', constructAPI);
module.exports = router => {
// Note that we wrap the api controller in a function that passes
// the original args through because a new api controller is generated
// every time the schema changes. We can't pass express a direct
// reference to the api controller on startup, or it will
// never update the reference to point at the latest version of the
// controller using the latest schema
router
.route('/')
.get((...args) => api(...args))
.post((...args) => api(...args));
return router;
};
In apollo-server-express#2, access to the middleware is hidden away, and there are 2 new, more declarative ways of using the library, neither of which - at first glance - appear compatible with updating the schema without stopping the server, fetching the new schema and starting again with the new data, which is downtime I'd like to avoid.
Can anyone suggest a way of getting this setup to work with apollo#2?

Using Places Library in App maker

Is there a way to call PlacesServices' getDetails function from App Maker?
I have the Place ID from the Geocoder but I'd like to be able to get details about the place.
At this time there is no built-in Places service in Apps Script and you'll need to through these steps to make it work:
Go to Google Cloud Console
Create a brand new project or use the project associated with your App Maker deployment:
Using left navigation menu go to APIs & Services -> Dashboard
Click + Enable APIs and Services button
Search for Google Places API Web Service and enable it
Go to APIs & Services -> Credentials and create new API key if you don't have one
Back in App Maker! =) Create a server script:
var API_KEY = 'PUT_YOUR_API_KEY_HERE';
var PLACES_URL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=';
function getPlaceDetails_(placeId) {
var URL = PLACES_URL + placeId + '&key=' + API_KEY;
var response = UrlFetchApp.fetch(URL);
var json = response.getContentText();
var placeDetails = JSON.parse(json);
return placeDetails;
}
This snippet is cornerstone for further scripting. You can use it with Calculated Model or just call it using google.script.run from client (note that for the second case you'll need to make this function public by removing underscore in the end of function name).

In Memory HTTP server Asp.net WebAPI

I am trying to understand how the self host configuration based Integration Tests are running.
In the code below, Should I be registering my config with the WebApiConfig. Registering or not seems to make no difference.
Is the full pipeline really being tested or is this an illusion? Since, If I am not using the config and the routes defined in my API instead declaring my own as I have done here, I am probably just not testing the full pipleine.
Is there any othere way of testing the api completely. The code below is testing a lot of things besides just my pipeline(like the client, SelfHosting etc..). This seems like an overkill to me. Any ideas ?
var config = new HttpSelfHostConfiguration("http://localhost:9090/");
config.Routes.MapHttpRoute("Default", "{api}/{controller}/{id}", new { id = RouteParameter.Optional });
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
MyApiProject.WebApiConfig.Register(config);
using (var server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
using (var client = new HttpClient())
{
using (var response = client.PostAsync("http://localhost:9090/api/login",
new FormUrlEncodedContent(new List<KeyValuePair<string,string>> { new KeyValuePair<string, strin("Foo","Bar)}), CancellationToken.None).Result)
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
using (var response = client.GetAsync("http://localhost:9090/api/login").Result)
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
server.CloseAsync().Wait();
}
If you just want to test your controllers, you can write more targeted unit tests to test them. If you want to test the full pipeline your code looks fine except that instead of using a selfhost, you can just use HttpServer saving the network overhead. Also, if you are testing the full pipeline it is better to use the routes that you have in your actual app rather than adding a new route as that would be testing routing as well.
Also, refer to this blog post by Youssef for some ideas on testing your web APIs.

Resources